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
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.
A possible quick alternative maybe this
https://github.com/gurgeh/selfspy
It claims to work on both mac and windows. It is based on pyhook on the windows part.
Good luck.
Related
This problem involves the collision of several problems, all of which I understand only somewhat well, but I include them together because they could all be the entry point for a solution. Here is the best description I can give.
I have an app, in python. (I imagine I could theoretically solve all of these problems by learning Cocoa and ObjectiveC, but that seems like QUITE a lift, for this problem -- AND, as noted below, this problem may not actually be related to python, really, at all. I just don't know.) A CORE feature of this app is to trigger a minigame, with a hotkey -- meaning, the hotkey itself is fundamental to the desired functionality. And furthermore, I would really like to package this app, to let other people use it. (Locally, it works great! Hey!)
The problem starts with the fact that adding the hotkey -- which I am doing with
import keyboard
keyboard.add_hotkey('windows+shift+y', trigger_minigame)
-- requires root access. Due to DIRE WARNINGS in another SO post Forcing a GUI application to run as root (which, honestly, I only vaguely understand), I would like to grant that access to ONLY this part of the program. I IMAGINE, such an approach would look something like this:
# needs_root.py
import keyboard
from shouldnt_have_root import trigger_minigame
keyboard.add_hotkey('windows+shift+y', trigger_minigame)
# shouldnt_have_root.py
def minigame():
buncha pygame, GUI stuff (which is dangerous???)
def trigger_minigame():
adds event to minigame's event queue
# bash script
sudo python needs_root.py
HOWEVER -- there are several major challenges!
The biggest is that I don't even know if THAT is safe, since I don't know how security and permissions (especially with imports) works at all! And more generally, how dangerous are the imports? It appears that I may in fact have to import substantially more, to make it clear what event queue the trigger is adding an event TO -- and I don't know how to have that communication happen, while still isolating the GUI parts (or generally dangerous ones) from unnecessary and hazardous access.
There's another layer too though; packaging it through pyinstaller means that I can't target the scripts directly, because they'll have been turned into binaries, but according to THIS answer Packaging multiple scripts in PyInstaller it appears I can just target the binaries instead, i.e. have the first binary call
osascript -e 'do shell script "python needs_root_binary" with admin.'
to get the user to bless only the necessary part, but I don't know if that will put OTHER obstacles, or vulnerabilities (or inter-file communication difficulties), in the way.
LAST, I could try STARTING as root, and then switching away from it, as soon as the hotkey is set (and before anything else happens) -- but would that be safe? I'm still worried about the fact that it involves running sudo on the whole app.
In any event --
is this as big a mess as it feels?
How do I give root access to only a piece of a packaged .app, that I've written in python?
I'd advice You to:
enable the root access,
write the script,
disable the root access
as it's closer described in here.
The Pyinstaller is another chapter. When I was making software requiring usage of hotkeys, I was forced to use another than keyboard, because it wasn't working properly on PC without Python, therefore I made a hotkey with tkinter built-in function canvas.bind() (more info here).
Hopefully I helped.
You can not run a specific Python function as root, only the Python process executing your script can be run with elevated permissions.
So my answer is: your problem as described is unsolvable.
I'm currently at a crossroads. I'm somewhat versed in Python (2.7) and would really like to start getting into GUI to give my (although mini) projects some more depth and versibility.
For the most part, my scripts don't use anything graphical so this is the first time I'm dipping my toes in this water.
That said, I've tried using pygame and tkinter but seem to fail at every turn to get something up and running (although I had some slight success with pygame)
Am I correct to understand that for both I need X started in order to generate any type of interface, and with that, so I need X to get any type of input (touchscreen presses)?
Thanks in advance!
In order to use tkinter, you must have a graphics system running. For Windows and OSX that simply means you need to be logged in (ie: can't run as a service). For linux and other unix-like systems that means that you must have X running.
Neither tkinter nor any of the other common GUI toolkits will write directly to the screen.
I'm gonna give an alternative answer. If you know HTML, CSS and Javascript (or have time to give it a try) I would recommend using Flask, http://flask.pocoo.org/.
With flask you can create websites but you can also (as I am using it) let it be your GUI. It will work on any device and looks really good :).
I'm just starting on an application that will need to be able to receive multimedia key (play/pause, skip, previous) presses. I'm looking to target Mac, Linux (major distros), and Windows. I've seen a solution for GNOME that appears to do what I need, but as simple as it sounds, never anything that can pick up those keys on all major platforms. I also need to be able to pick up the keys globally, since the application will run in the background and won't ever have focus.
Currently, I'm not strongly tied to Python, but since I'd like to be able to target multiple platforms, Python seemed like the way to go. Has anyone written any cross-platform libraries that can do this? I haven't been able to find any that work.
PyQT looks like a potentially viable option, but some people have hinted that global key detection may be problematic on OSX.
With PyQt (or PySide) you can use the Qt::AA_CaptureMultimediaKeys application flag to enable cross-platform capturing of multimedia keys. In principle, using that flag your Qt program should be able to receive keyboard events when the user presses multimedia keys such as Play (Qt::Key_MediaPlay), Stop (Qt::Key_MediaStop), Pause (Qt::Key_MediaPause) etc. For a full list of supported keys, have a look at the documentation.
I cannot say if all keys will be supported on all platforms, but in general Qt aims to provide very good interoperability between different operating systems. I think with a simple prototype you should be able to answer that question really quick (I don't have access to a MacOS environment so I cannot test it there, but for Windows & Linux it should work). For more information on how to process keyboard events using Qt, have a look at the documentation of the QKeyEvent class.
I took over python-mmkeys a few months ago. I actually never tried to compile it, but it was included in the code of a project.
It is PyGTK dependant, but it is available on GNU/Linux, MacOX, and Windows.
The code is pretty easy to use:
import mmkeys
keys = mmkeys.Mmkeys()
keys.connect("mm_prev", previous_cb)
keys.connect("mm_next", next_cb)
keys.connect("mm_playpause", playpause_cb)
I'm planning to develop a GUI application that uses curses. The idea is to provide an extra interface for a web interface, so that everything on the web site could also be done via the UI.
Basically, it should be platform independent: the user would have to SSH to the server after which the UI would automatically take over.
First of all, is this doable? As far as I understand, it would be platform independent as long as the end-user had the proper terminal software installed. Correct me, if I'm wrong.
I was planning to use Python for this, as it is the language I'm the most proficient in. Python comes with the ncurses library and Urwid, which I've been told, is quite good.
After having a quick test with Urwid, I had some problems. The thing is, I'm quite worried that I won't find answers to the problems that I will encounter down the road because apparently curses UI-s aren't all the rage nowadays. Documentation and examples are thus quite scarce.
In conclusion, should really I embark on this and quit my whining or drop the idea altogether? Any other suggestions?
It's certainly possible, and curses-based applications are still written regularly (e.g. PuDB is only 14 months old) although maybe not very often.
Did you try asking questions on the Urwid mailing list and/or IRC channel?
oh my, wouldn't this be a dream!
i've seen a couple of things out there to varying degrees of success.
Morticious Thrind: http://thrind.xamai.ca/
future death toll: http://f-dt.com/?wptheme=wp-cli
wordpress yadda yadda, this could be as simple as a 960/blueprint CSS, prototype.js, and a oneliner:
//TODO: Implement useful functionality && unit tests && documentation
//TODO: read
try { eval($F(x)); } catch (e) { panic(); }
BUT! this type of thing is pretty radical. i mean- ANYTHING can happen on the canvas of a web-browser these days, but any terminal emulator or lynx serves this purpose with flare.
also be sure to check out: https://stackoverflow.com/questions/472644/javascript-collection-of-one-line-useful-functions
the real question is what sort of software you plan on ncursing (sic,pun,etc.)-- it probably already has some rather useful command-line interfaces (sh).
It can be done but it's a struggle. I would recommend improving the web interface. You can use JavaScript to add keyboard shortcuts, for example, which can be very helpful for a faster workflow (see Gmail's interface, for example).
I am trying to write a cross-platform python program that would run in the background, monitor all keyboard events and when it sees some specific shortcuts, it generates one or more keyboard events of its own. For example, this could be handy to have Ctrl-# mapped to "my.email#address", so that every time some program asks me for my email address I just need to type Ctrl-#.
I know such programs already exist, and I am reinventing the wheel... but my goal is just to learn more about low-level keyboard APIs. Moreover, the answer to this question might be useful to other programmers, for example if they want to startup an SSH connection which requires a password, without using pexpect.
Thanks for your help.
Note: there is a similar question but it is limited to the Windows platform, and does not require python. I am looking for a cross-platform python api. There are also other questions related to keyboard events, but apparently they are not interested in system-wide keyboard events, just application-specific keyboard shortcuts.
Edit: I should probably add a disclaimer here: I do not want to write a keylogger. If I needed a keylogger, I could download one off the web a anyway. ;-)
There is no such API. My solution was to write a helper module which would use a different helper depending on the value of os.name.
On Windows, use the Win32 extensions.
On Linux, things are a bit more complex since real OSes protect their users against keyloggers[*]. So here, you will need a root process which watches one of[] the handles in /dev/input/. Your best bet is probably looking for an entry below /dev/input/by-path/ which contains the strings "kbd" or "keyboard". That should work in most cases.
[*]: Jeez, not even my virus/trojan scanner will complain when I start a Python program which hooks into the keyboard events...
As the guy that wrote the original pykeylogger linux port, I can say there isn't really a cross platform one. Essentially I rewrote the pyhook API for keyboard events to capture from the xserver itself, using the record extension. Of course, this assumes the record extension is there, loaded into the x server.
From there, it's essentially just detecting if you're on windows, or linux, and then loading the correct module for the OS. Everything else should be identical.
Take a look at the pykeylogger source, in pyxhook.py for the class and implimentation. Otherwise, just load that module, or pyhook instead, depending on OS.
I've made a few tests on Ubuntu 9.10. pykeylogger doesn't seems to be working. I've tryied to change the /etc/X11/xorg.conf in order to allow module to be loaded but in that specific version of ubuntu there is no xorg.conf. So, in my opiniion pykelogger is NOT working on ubuntu 9.10 !!
Cross-platform UI libraries such as Tkinter or wxPython have API for keyboard events. Using these you could map «CTRL» + «#» to an action.
On linux, you might want to have a look at pykeylogger. For some strange reason, reading from /dev/input/.... doesn't always work when X is running. For example it doesn't work on ubuntu 8.10. Pykeylogger uses xlib, which works exactly when the other way doesn't. I'm still looking into this, so if you find a simpler way of doing this, please tell me.
Under Linux it's possible to do this quite easily with Xlib. See this page for details:
http://www.larsen-b.com/Article/184.html