Something like pyHook on OS X
Question: I am actually working with **pyHook** , but I'd like to write my program for
OS X too. If someone know such a module ... I've been looking on the internet
for a while, but nothing really relevant.

-> The idea is to be able to record keystrokes outside the python app. My application is a _community statistics_ builder, so it would be great to have statistics from OS X too. 

Thanks in advance ;)

**Edit** : PyHook : Record keystrokes and other things outside the python app
<http://sourceforge.net/apps/mediawiki/pyhook/index.php?title=PyHook_Tutorial>
http://pyhook.sourceforge.net/doc_1.5.0/
<http://sourceforge.net/apps/mediawiki/pyhook/index.php?title=Main_Page>


Answer: As far as I know, there is no Python library for this, so you're going to be
calling native APIs. The good news is that PyObjC (which comes with the built-
in Python on recent OS releases) often makes that easy.

There are two major options. For either of these to work, your app has to have
a Cocoa/CoreFoundation runloop (just as in Windows, a lot of things require
you to be a "Windows GUI executable" rather than a "command line executable"),
which I won't explain how to do here. (Find a good tutorial for building GUI
apps in Python, if you don't know how, because that's the simplest way.)

The easy option is the Cocoa global event monitor API. However, it has some
major limitations. You only get events that are going to another app--which
means media keys, global hotkeys, and keys that are for whatever reason
ignored will not show up. Also, you need to be "trusted for accessibility".
(The simplest way to do that is to ask the user to turn it on globally, in the
Universal Access panel of System Preferences.)

The hard option is the Quartz event tap API. It's a lot more flexible, and it
only requires exactly the appropriate rights (which, depending on the settings
you use, may include being trusted for accessibility and/or running as root),
and it's a lot more powerful, but it takes a lot more work to get started, and
it's possible to screw up your system if you get it wrong (e.g., by eating all
keystrokes and mouse events so they never get to the OS and you can't reboot
except with the power button).

For references on all of the relevant functions, see
<https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/nsevent_Class/Reference/Reference.html>
(for NSEvent) and
<https://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html>
(for Quartz events). A bit of googling should turn up lots of sample code out
there in Objective C (for NSEvent) or C (for CGEventTap), but little or
nothing in Python, so I'll show some little fragments that illustrate how
you'd port the samples to Python:

    
    
    import Cocoa
    def evthandler(event):
      pass # this is where you do stuff; see NSEvent documentation for event
    observer = Cocoa.NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDown, evthandler)
    # when you're done
    Cocoa.NSEvent.removeMonitor_(observer)
    
    import Quartz
    def evthandler(proxy, type, event, refcon):
        pass # Here's where you do your stuff; see CGEventTapCallback
        return event
    source = Quartz.CGEventSourceCreate(Quartz.kCGEventSourceStateHIDSystemState)
    tap = Quartz.CGEventTapCreate(Quartz.kCGSessionEventTap,
                                  Quartz.kCGHeadInsertEventTap,
                                  Quartz.kCGEventTapOptionListenOnly,
                                  (Quartz.CGEventMaskBit(Quartz.kCGEventKeyDown) |
                                   Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp)),
                                  handler,
                                  refcon)
    

Another option, at about the same level as Quartz events, is Carbon events
(starting with InstallEventHandler). However, Carbon is obsolete, and on top
of that, it's harder to get at from Python, so unless you have some specific
reason to go this way, don't.

There are some other ways to get to the same point—e.g., use
DYLD_INSERT_LIBRARIES or SIMBL to get some code inserted into each app—but I
can't think of anything else that can be done in pure Python.

