Open tartavull opened 5 years ago
Think about making a game. Wanting to update the screen but then waiting for user input. I guess you could run everything else in a thread but the keystroke input waiting. But then again why can't we run the keystroke detection in a thread?
a little late but for others looking for this. This code is only testes for the new Version beeing developed under #79
from threading import Thread
from time import time, sleep
from readchar import key, readkey
# construct an inverted code -> key-name mapping
# we need to revese the items so that aliases won't overrive the original name later on
known_keys = {v: k for k, v in reversed(vars(key).items()) if not k.startswith("__")}
def keylogger():
global running
print("starting keylogger...")
while running:
try:
data = readkey()
except KeyboardInterrupt:
running = False
break
if data in known_keys:
data = known_keys[data]
print(f"{data}-key was pressed")
print("stopping keylogger...")
def main():
while running:
print(f"LOG: current time is {time()}")
sleep(1)
running = True
if __name__ == "__main__":
Thread(name="keylogger", target=keylogger).start()
main()
For cases where a timeout is required, spawning a subprocess instead of a thread means it can be killed. See the following:
from multiprocessing import Process
from time import sleep, time
from readchar import key, readkey
# construct an inverted code -> key-name mapping
# we need to revese the items so that aliases won't overrive the original name later on
known_keys = {v: k for k, v in reversed(vars(key).items()) if not k.startswith("__")}
def keylogger():
print("starting keylogger...")
while True:
try:
data = readkey()
except KeyboardInterrupt:
break
if data in known_keys:
data = known_keys[data]
print(f"{data}-key was pressed")
if __name__ == "__main__":
p = Process(name="keylogger", target=keylogger)
p.start()
sleep(5)
print("timeout..")
p.kill()
I have a strange case where CTRL+C causes readchar.readkey() to block forever.
The thread calling readchar.readkey() is a background thread (reason explained below)
Unfortunately I can't reproduce it in a simple code snippet, It occures in an app with a lot of things going on.
I was able to solve the problem by replacing readchar.config.INTERRUPT_KEYS with an empty array:
readchar.config.INTERRUPT_KEYS = []
@AuHau not blocking the main thread is essential in use cases where you want to intercept os signals, the main thread must be paused with signal.pause()
if __name__ == "__main__":
def _sigint(p1, p2):
print("sigint received")
signal.signal(signal.SIGINT, _sigint)
Thread(name="keyreader", target=keylogger).start()
signal.pause()
@max-l without a way to reproduce, I can really help you. However, here are some thought on the matter:
When you start the separate thread, you also need to terminate both threads in some way. You may have had cases where you had to press CTRL+C
two times to stop the program, once for each thread. One other way is to set a flag when one terminates, that also stops the other one (like running
in the example)
Now if you mess around with SIGINT
you might get cases, where a CTRL+C
doesn't reach readchar properly, because it is interrupted beforehand or something similar.
If you find a way to reproduce this Problem, feel free to open an issue
As this is only for documentation purposous, I will lock it.
If you have problem or suggestions, feel free to open another issue
Hmm not sure, but to be honest, why would you like to do that? It does not really make sense to me...