Radar32
Radar32

Reputation: 35

Listening on stdin while writing to serial port

I have a separate Python process that, after starting, continuously outputs through its stdout trajectory points to the main app which carries them, after some processing, to a device over a serial port. It can non-deterministically happen that sending trajectory points would have to be stopped. If that happens, then a slow-down trajectory points would have to be generated and send, and only the process has data to do it. However I can't listen to a stop command in that process with, for ex., input(), and generate trajectory because of GIL. How can I both listen on stdin and generate the trajectory?

I don't want to place the trajectory generation or the slow-down bit in the main app, because it will complicate things a lot. I also would rather not write the whole app in another language like C++.

Upvotes: 0

Views: 80

Answers (1)

Ahmed AEK
Ahmed AEK

Reputation: 18000

you can listen on stdin in a daemon worker thread, and notify the main thread through a threading.Event, daemon threads are fire-and-forget, so they are used for such tasks.

import threading
import time

stop_event = threading.Event()
def listen_for_stop():
    while True:
        input_value = input()
        if input_value == "stop":
            stop_event.set()
            break

listener = threading.Thread(target=listen_for_stop, 
                            daemon=True)
listener.start()
while True:
    if not stop_event.is_set():
        print("outputting trajectory")
    else:
        print("outputting stop tranjectory")
        break
    time.sleep(1)
outputting trajectory
stop
outputting stop tranjectory

the GIL stops threads from executing in parallel, they just take turns executing (5-10ms time slices), but the listener is blocked reading input so it is sleeping and the main thread is not interrupted, the worker only wakes up when input arrives.

you don't necessarily need to listen on stdin, you can do that on a named pipe or a socket if you want to leave stdin for other uses, and at least on windows using a socket allows asnychronous listening on the socket with asyncio, whereas on unix you can listen on stdin asynchronously, which you will need to do if you want to stop the listener. (windows doesn't support async reads from stdin)

Upvotes: 0

Related Questions