I'm trying to find a way to shorten a time.sleep(600) if the user inputs a key, without resorting to some ugly hack like:
key_pressed = False
for i in range(600):
key_pressed = key_was_pressed()
if not key_pressed:
time.sleep(1)
else:
break
This is a cross-platform adaptation of an implementation using signal.alarm interrupt (an idea which is not available on Windows). This code should work for Linux, macOS, and Windows. The 3rd-party helper library readchar can be installed with pip install readchar.
import os
import signal
import sys
from threading import Timer
from readchar import readkey
def wait_for(key="x", timeout=600):
pid = os.getpid()
sig = signal.CTRL_C_EVENT if os.name == "nt" else signal.SIGINT
timer = Timer(timeout, lambda: os.kill(pid, sig))
print(f"waiting {timeout}s for user to press {key!r} ...")
timer.start() # spawn a worker thread to interrupt us later
while True:
k = readkey()
print(f"received {k!r}")
if k == key:
timer.cancel() # cancel the timer
print("breaking")
break
def main():
import sys
try:
wait_for(key=sys.argv[1], timeout=int(sys.argv[2]))
except KeyboardInterrupt as err:
print("user took too long")
if __name__ == "__main__":
main()
Why is the input() after the if statement not working?
I need some help, the input() after the if statement is supposed to stop the script, however it just continues. If i give it another command, for example print("...") or time.sleep(10) it will execute, it is only the input() that does not work. Any ideas?
Edit: Because it might not be clear what the intention is. When asking for an input after the if statement the script should wait before continuing. This is because I want it to pause after I move the mouse so that it does not keep spamming the keys, but I am able to resume it if needed.
import time
from pynput.keyboard import Key, Controller as KeyController
from pynput.mouse import Controller as MouseController
key = KeyController()
mouse = MouseController()
def f1_toggle():
key.press(Key.f1)
key.release(Key.f1)
def enter_toggle():
key.press(Key.enter)
key.release(Key.enter)
input("Press any key to start:")
time.sleep(5)
while True:
start_position = mouse.position
key.press(Key.ctrl_l)
print("Ctrl pressed")
f1_toggle()
print("F1 toggled")
key.release(Key.ctrl_l)
print("Ctrl released")
time.sleep(1)
enter_toggle()
print("Enter toggled")
time.sleep(.5)
end_position = mouse.position
if start_position != end_position:
input("Press any key to continue ")
You're calling enter_toggle() before you ask for input. This is simulating pressing the Enter key. This is being used as the response to the input() call, so it doesn't wait for the user to enter something manually.
Are you sure the two variables are different?
I don't have pyinput, and I am using python 3.8, but in my computer, the input isn't skipped (I commented the pyinput).
Try this:
try:
input("Press any key to continue ")
except Exception as e:
print(e);
Try to see if this helps and what it prints.
How can I capture a key press (key logging) in Linux?
For Windows exist pyHook library but I dont know how to do it in Linux.
You can use pyxhook:
#!/usr/bin/env python
import pyxhook
def OnKeyPress(event):
print (event.Key)
if event.Ascii == 32:
exit(0)
hm = pyxhook.HookManager()
hm.KeyDown = OnKeyPress
hm.HookKeyboard()
hm.start()
sudo apt-get install python-xlib
https://github.com/JeffHoogland/pyxhook
#!/usr/bin/env python
import pyxhook
import time
#This function is called every time a key is presssed
def kbevent( event ):
#print key info
print event
#If the ascii value matches spacebar, terminate the while loop
if event.Ascii == 32:
global running
running = False
#Create hookmanager
hookman = pyxhook.HookManager()
#Define our callback to fire when a key is pressed down
hookman.KeyDown = kbevent
#Hook the keyboard
hookman.HookKeyboard()
#Start our listener
hookman.start()
#Create a loop to keep the application running
running = True
while running:
time.sleep(0.1)
#Close the listener when we are done
hookman.cancel()
I'm working on a Python script using Blessed and can't get the 'hidden_cursor()' function to work properly.
It will successfully hide the cursor but it won't set the visibility back on exit.
This is what I tried so far:
with term.hidden_cursor():
while True:
command = raw_input (term.move(27, 2) + "")
if command == "X":
os.system('clear')
sys.exit()
else:
os.system('clear')
main('self')
And here's the full script: https://gist.github.com/lovemac15/c5e71e0b8aa428693e5b
Thanks! :D
Try changing the control flow to be sure to exit the with block:
with term.hidden_cursor():
while True:
command = raw_input (term.move(27, 2) + "")
if command == "X":
os.system('clear')
sys.exit()
else:
os.system('clear')
break
main('self')
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.