Search code examples
pythonfile-iopyobjc

Write to NSLog and file PythonObjC


I'm trying to modify a script to additionally print to a log file. It already uses NSLog(). I'm definitely still learning Python... Anyways, here's what I have so far:

# cocoa_keypress_monitor.py by Bjarte Johansen is licensed under a 
# License: http://ljos.mit-license.org/

from AppKit import NSApplication, NSApp
from Foundation import NSObject, NSLog
from Cocoa import NSEvent, NSKeyDownMask
from PyObjCTools import AppHelper
import sys

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, notification):
        mask = NSKeyDownMask
        NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(mask, handler)

def handler(event):
    try:
        NSLog(u"%@", event)
        with open("/Users/Zachary/Downloads/foo.txt", "a", 0) as myfile:
            myfile.write(u"%@", event)
    except KeyboardInterrupt:
        AppHelper.stopEventLoop()

def main():
    app = NSApplication.sharedApplication()
    delegate = AppDelegate.alloc().init()
    NSApp().setDelegate_(delegate)
    AppHelper.runEventLoop()

if __name__ == '__main__':
    main()

As you can see, I attempted to pass myfile.write() the same data as NSLog(), but Python doesn't like that and I don't know how to do it properly.


Solution

  • The argument to file.write() is not a format string like NSLog()'s argument, it's just a single regular string. You need to coerce the NSEvent object to be a string, by passing it to Python's str() function. (PyObjC knows to call an Objective-C object's -description method, as NSLog() does, in that situation.)

    You should also note that %@ is not a valid format specifier for Python format strings: it is only used in ObjC. Actually, the preferred format string syntax in Python now doesn't even use percent escapes. If you wanted to format the NSEvent into a Python string explicitly, you would do something like: "{}".format(event)