I was playing around with info I can get from key presses and mouse events in python and everything seems to work except when I quit the program I get this error.
runtime error R6031 - Attempt to initialize the CRT more than once. This indicates a bug in your application.
Here is my code not that it only happens when I press 'q' and the program quits.
import pythoncom, pyHook, sys
def OnMouseEvent(event):
# called when mouse events are received
print 'MessageName:',event.MessageName
print 'Message:',event.Message
print 'Time:',event.Time
print 'Window:',event.Window
print 'WindowName:',event.WindowName
print 'Position:',event.Position
print 'Wheel:',event.Wheel
print 'Injected:',event.Injected
print '---'
return True
def OnKeyboardEvent(event):
print "Message Name: ", event.MessageName
print 'Message:',event.Message
print 'Time:',event.Time
print 'Window:',event.Window
print 'WindowName:',event.WindowName
print 'Ascii:', event.Ascii, chr(event.Ascii)
print 'Key:', event.Key
print 'KeyID:', event.KeyID
print 'ScanCode:', event.ScanCode
print 'Extended:', event.Extended
print 'Injected:', event.Injected
print 'Alt', event.Alt
print 'Transition', event.Transition
print '---'
if chr(event.Ascii) == 'q':
sys.exit()
return True
hm = pyHook.HookManager()
hm.KeyDown = OnKeyboardEvent
hm.MouseDown = OnMouseEvent
hm.HookKeyboard()
hm.HookMouse()
pythoncom.PumpMessages()
Thanks in advance for the help!
You have to "unhook" the hooks that you created to do a proper exit.
To terminate the "pythoncom.PumpMessages()" ever-lasting-loop:
if chr(event.Ascii) == 'q':
ctypes.windll.user32.PostQuitMessage(0)
The following code works correctly on Windows 7 with Python 2.7.6.
I haven't yet figured out how to make it work under Python 3.4, but I'll be back when I know!
import pythoncom, pyHook
import ctypes
import sys
def OnMouseEvent(event):
# called when mouse events are received
print('MessageName:', event.MessageName)
print('Message:', event.Message)
print('Time:', event.Time)
print('Window:', event.Window)
print('WindowName:', event.WindowName)
print('Position:', event.Position)
print('Wheel:', event.Wheel)
print('Injected:', event.Injected)
print('---')
return True
def OnKeyboardEvent(event):
print("Message Name: ", event.MessageName)
print('Message:', event.Message)
print('Time:', event.Time)
print('Window:', event.Window)
print('WindowName:', event.WindowName)
print('Ascii:', event.Ascii, chr(event.Ascii))
print('Key:', event.Key)
print('KeyID:', event.KeyID)
print('ScanCode:', event.ScanCode)
print('Extended:', event.Extended)
print('Injected:', event.Injected)
print('Alt', event.Alt)
print('Transition', event.Transition)
print('---')
if chr(event.Ascii) == 'q':
ctypes.windll.user32.PostQuitMessage(0)
return True
print("")
print('Python version:')
print((sys.version))
print("")
hm = pyHook.HookManager() # create a hook manager
hm.MouseAll = OnMouseEvent # watch for all mouse events
hm.HookMouse() # set the hook
hm.KeyDown = OnKeyboardEvent # watch for "OnKeyboardEvent"
hm.HookKeyboard() # set the hook
pythoncom.PumpMessages()
# if you reached this point you have terminated the program correctly!
# flush and close any open files etc.
hm.UnhookMouse()
hm.UnhookKeyboard()
print("")
print("The end of Mouse and KBD test!")
print("")
LushIsTheLanguage's answer does not solve the error.
The error comes on 64 bit Python installations, not 32 bit.
It is caused by HookMouse, if that is disabled then the error disappears.
So, it's a bug in PyHook/HookMouse for 64 bit Python installations. The quickest solution is to switch to 32 bit Python.
The suggestion of LushIsTheLanguage has partly solved one problem I was facing for long time. I have embedded python interpreter in one multithreaded C code with GTK. I could run my *.py script (with pyHook imported in it) from the GTK based GUI only for first time. Next time when I used to run it the full code used to crash. Without pyHook imported scripts I could run any number of times from my GUI.
Now after calling hm.UnhookMouse() and hm.UnhookKeyboard() at the end of the python script I can run it more that one time from my GUI. However still it is crashing after four or five times.
In my *.py script I am not using "pythoncom.PumpMessages()", rather I am using while loop with "pythoncom.PumpWaitingMessages()", so that I can break it once any key is pressed.
key_scn_code = -1
while key_scn_code < 0:
time.sleep(0.05)
if os.name == 'nt':
pythoncom.PumpWaitingMessages()
my callback for keyboard-events is something like the following
def kbevent_callback( key_event ):
global key_scn_code
key_scn_code = key_event.ScanCode
return True
I have checked it in Win-7 64-bit (python 2.7 32-bit) and Linux 64-bit (using pyxhook) with python 2.7. Both have similar problem. Does any one have any suggestion.
Related
Really more of a question here. Based on pyHook's tutorial, the .HookManager().OnMouseEvent event variable in the function has a .Injected attribute. I couldn't find any information about it, does anyone know what it is? I tried doing
event.Injected = '<char to inject>'
but it didn't work.
Disclaimer: I'm not expert of this stuff,
I'm just sharing my observations about the tutorial and the documentation,
in the hope that it will be helpful.
The attributes on event are not for you to set manually,
but for your event handlers to read and act upon.
As you can see in the documentation of KeyboardEvent and MouseEvent,
the purpose of the Injected instance variables is to check if the event was generated programmatically or not.
I think, this means events that your handlers receive from mouse and keyboard activity, will always have this variable False.
And there is a way to generate events programmatically,
I imagine for the purpose of testing your handlers.
And the method appear to be HookManager.KeyboardSwitch and HookManager.MouseSwitch.
Try this for example. Create a simple program to see the details of some real keyboard events:
import pythoncom, pyHook
def OnKeyboardEvent(event):
print 'MessageName:',event.MessageName
print 'Message:',event.Message
print 'Time:',event.Time
print 'Window:',event.Window
print 'WindowName:',event.WindowName
print 'Ascii:', event.Ascii, chr(event.Ascii)
print 'Key:', event.Key
print 'KeyID:', event.KeyID
print 'ScanCode:', event.ScanCode
print 'Extended:', event.Extended
print 'Injected:', event.Injected
print 'Alt', event.Alt
print 'Transition', event.Transition
print '---'
# return True to pass the event to other handlers
return True
# create a hook manager
hm = pyHook.HookManager()
# watch for key press events
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# wait forever
pythoncom.PumpMessages()
Press a couple of keys and observe the outputs. Press Control-C to terminate the program.
Then, to generate some events programmatically and see what they look like,
try something like this:
import pythoncom, pyHook
def OnKeyboardEvent(event):
# ... same code as in previous sample ...
# create a hook manager
hm = pyHook.HookManager()
# watch for key press events
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# send keyboard event programmatically
msg = ... # a value like in the "Message: ..." output in the previous run
vk_code = ... # a value like in the "KeyID: ..." output in the previous run
scan_code = ... # a value like in the "ScanCode: ..." output in the previous run
ascii = ... # a value like in the "Ascii: ..." output in the previous run
flags = 0x10 # see http://pyhook.sourceforge.net/doc_1.5.0/pyhook.HookManager-pysrc.html#KeyboardEvent.IsInjected
time = ... # a value like in the "Time: ..." output in the previous run
hwnd = ... # a value like in the "Window: ..." output in the previous run
win_name = ... # a value like in the "WindowName: ..." output in the previous run
hm.KeyboardSwitch(msg, vk_code, scan_code, ascii, flags, time, hwnd, win_name)
After you set appropriate values,
and run this program,
you should see "Injected: True" in the output.
I think this is the basic idea, and similarly for mouse events.
Unfortunately I'm not able to test this,
because it seems pyHook is a library for Windows OS, which I don't have.
Thank you guys for seeing my post.
First, the following is my code:
import os
print("You can create your own message for alarm.")
user_message = input(">> ")
print("\n<< Sample alarm sound >>")
for time in range(0, 3):
os.system('say ' + user_message) # this code makes sound.
print("\nOkay, The alarm has been set.")
"""
##### My problem is here #####
##### THIS IS NOT STOPPED #####
while True:
try:
os.system('say ' + user_message)
except KeyboardInterrupt:
print("Alarm stopped")
exit(0)
"""
My problem is that Ctrl + C does not work!
I tried changing position of try block, and making signal(SIGINT) catching function.
But those also does not work.
I have seen https://stackoverflow.com/a/8335212/5247212, https://stackoverflow.com/a/32923070/5247212, and other several answers about this problem.
I am using MAC OS(10.12.3) and python 3.5.2.
This is expected behaviour, as os.system() is a thin wrapper around the C function system(). As noted in the man page, the parent process ignores SIGINT during the execution of the command. In order to exit the loop, you have to manually check the exit code of the child process (this is also mentioned in the man page):
import os
import signal
while True:
code = os.system('sleep 1000')
if code == signal.SIGINT:
print('Awakened')
break
However, the preferred (and more pythonic) way to achieve the same result is to use the subprocess module:
import subprocess
while True:
try:
subprocess.run(('sleep', '1000'))
except KeyboardInterrupt:
print('Awakened')
break
Your code would then look like something like this:
import subprocess
print("You can create your own message for alarm.")
user_message = input(">> ")
print("\n<< Sample alarm sound >>")
for time in range(0, 3):
subprocess.run(['say', user_message]) # this code makes sound.
print("\nOkay, The alarm has been set.")
while True:
try:
subprocess.run(['say', user_message])
except KeyBoardInterrupt:
print("Alarm terminated")
exit(0)
As an added note, subprocess.run() is only available in Python 3.5+. You can use subprocess.call() to achieve the same effect in older versions of Python.
Also catch "SystemExit"
except (KeyboardInterrupt, SystemExit):
print("Alarm stopped")
The problem seems to be that Ctrl+C is captured by the subprocess you call via os.system. This subprocess reacts correspondingly, probably by terminating whatever it is doing. If so, the return value of os.system() will be not zero. You can use that to break the while loop.
Here's an example that works with me (substituting say by sleep):
import os
import sys
while True:
try:
if os.system('sleep 1 '):
raise KeyboardInterrupt
except KeyboardInterrupt:
print("Alarm stopped")
sys.exit(0)
If Ctrl-C is captured by the subprocess, which is the case here, the simplest solution is to check the return value of os.system(). For example in my case it returns value of 2 if Ctrl-C stops it, which is a SIGINT code.
import os
while True:
r = os.system(my_job)
if r == 2:
print('Stopped')
break
elif r != 0:
print('Some other error', r)
I'm wondering how I would go about having a function refresh itself every minute, and check if a certain file it open. I don't exactly know how to go about this, but heres an example of what I'm looking for:
def timedcheck():
if thisgame.exe is open:
print("The Program is Open!")
else:
print("The Program is closed!")
*waits 1 minute*
timedcheck()
I would also like the script to refresh the function "def timedcheck():" every minute, so it keeps checking if thisgame.exe is open.
I searched through the site already, all suggestions recommended using "import win32ui", which gives me an error when I do.
To repeat this check every minute:
def timedcheck():
while True:
if is_open("thisgame.exe"):
print("The Program is Open!")
else:
print("The Program is closed!")
sleep(60)
Since it's a .exe file, I assume that by "check if this file is open" you mean "check if thisgame.exe" is running. psutil should be helpful - I haven't tested the below code, so it may need some tweaking, but shows the general principle.
def is_open(proc_name):
import psutil
for process in psutil.process_iter():
if proc_name in process.name:
return True
return False
You can use sleep from the time module with an input of 60 for 1 minute delay between checks. You can open the file temporarily and close it if not needed. An IOError will occur if the file is already opened. Catch the error with an exception and the program will wait for another minute before trying again.
import time
def timedcheck():
try:
f = open('thisgame.exe')
f.close()
print("The Program is Closed!")
except IOError:
print("The Program is Already Open!")
time.sleep(60) #*program waits 1 minute*
timedcheck()
Here's a variation on #rkd91's answer:
import time
thisgame_isrunning = make_is_running("thisgame.exe")
def check():
if thisgame_isrunning():
print("The Program is Open!")
else:
print("The Program is closed!")
while True:
check() # ignore time it takes to run the check itself
time.sleep(60) # may wake up sooner/later than in a minute
where make_is_running():
import psutil # 3rd party module that needs to be installed
def make_is_running(program):
p = [None] # cache running process
def is_running():
if p[0] is None or not p[0].is_running():
# find program in the process list
p[0] = next((p for p in psutil.process_iter()
if p.name == program), None)
return p[0] is not None
return is_running
To install psutil on Windows for Python 2.7, you could run psutil-0.6.1.win32-py2.7.exe.
I have a timer, and need to know if any of the keys is pressed on any cycle. How do I do it?
If you are using Linux it's found in the curses module, if you use Windows it's in the msvcrt module.
I found following article really helpful in describing this topic - Event Driven Programming
If you are using Windows, Use PyHook If you like to know system wide key press events.
import pythoncom, pyHook
def OnKeyboardEvent(event):
print 'Ascii:', event.Ascii, chr(event.Ascii)
print 'Key:', event.Key
print 'KeyID:', event.KeyID
print 'ScanCode:', event.ScanCode
print 'Extended:', event.Extended
return True #for pass through key events, False to eat Keys
hm = pyHook.HookManager()
hm.KeyDown = OnKeyboardEvent
hm.HookKeyboard()
pythoncom.PumpMessages()
Try:
import sys
c = sys.stdin.read(1)
I have a Python program that sends keystrokes to another application using SendKeys. Some of the keystrokes, however, must be sent to the application after it does some processing (which takes an unknown amount of time). So far I have had to let the Python application know the processing was finished by Alt+Tabbing back to the DOS window and hitting Enter. I'd like to have a key combination (Shift+F1 or something like that) that I can hit in the receiving application that signals the Python program to continue without me having to switch back to the DOS window. How would I make it so I can detect keystrokes in Python even though the focus is on another window?
Have a look at pyHook.
It allows Keyboard hooking:
import pythoncom, pyHook
def OnKeyboardEvent(event):
print 'MessageName:',event.MessageName
print 'Message:',event.Message
print 'Time:',event.Time
print 'Window:',event.Window
print 'WindowName:',event.WindowName
print 'Ascii:', event.Ascii, chr(event.Ascii)
print 'Key:', event.Key
print 'KeyID:', event.KeyID
print 'ScanCode:', event.ScanCode
print 'Extended:', event.Extended
print 'Injected:', event.Injected
print 'Alt', event.Alt
print 'Transition', event.Transition
print '---'
# return True to pass the event to other handlers
return True
# create a hook manager
hm = pyHook.HookManager()
# watch for all mouse events
hm.KeyDown = OnKeyboardEvent
# set the hook
hm.HookKeyboard()
# wait forever
pythoncom.PumpMessages()