Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example: running this in a background thread? #43

Open
tartavull opened this issue Mar 12, 2019 · 6 comments
Open

Example: running this in a background thread? #43

tartavull opened this issue Mar 12, 2019 · 6 comments
Labels
question this is just a question, not a issue that requires a codechange

Comments

@tartavull
Copy link

No description provided.

@AuHau
Copy link
Collaborator

AuHau commented Mar 12, 2019

Hmm not sure, but to be honest, why would you like to do that? It does not really make sense to me...

@GrandMoff100
Copy link

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?

@Cube707
Copy link
Collaborator

Cube707 commented Jul 9, 2022

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()

@Cube707 Cube707 added the question this is just a question, not a issue that requires a codechange label Sep 5, 2022
@max-l
Copy link

max-l commented Oct 31, 2022

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()

@Cube707
Copy link
Collaborator

Cube707 commented Nov 6, 2022

@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

@Cube707 Cube707 changed the title is there any example of running this in a background thread? Example: running this in a background thread? Nov 9, 2022
@Cube707
Copy link
Collaborator

Cube707 commented Nov 9, 2022

As this is only for documentation purposous, I will lock it.

If you have problem or suggestions, feel free to open another issue

Repository owner locked and limited conversation to collaborators Nov 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question this is just a question, not a issue that requires a codechange
Projects
None yet
Development

No branches or pull requests

5 participants