(I have been advised to avoid python threads if possible!)
Bad rule of thumb. Here's a better one:
Only one thread will execute Python code at a time. Multiple threads can be blocking in a system call, for example reading from or writing to a pipe or a socket.
Ultimately I plan to have on script reading analogue sensors
That is exactly the pattern were Python threads will work just fine.
Use one Python
threading thread to read the sensors, and process them.
There are two options on how to handle the data. If the data is a stream (with readers expected to obtain successive readings, not just a snapshot), use a
queue. If the readers are only interested in snapshots, use a
threading.Lock to protect the stored sensor readings; before accessing or modifying them,
acquire() the lock, quickly copy the value, and
release() it.
Use a separate thread to respond to sensor queries. If the queries are limited to the local machine, use an Unix Domain datagram socket. If the queries are limited to local area network, use an UDP socket. This way there are no persistent connections to worry about, and each query is immediately responded with the corresponding answer. (You could use a protocol where the request names the sensors it is interested in, with the response containing the corresponding values; perhaps with a special query that returns the list of currently supported sensors. At such low data rates, ASCII text is fine.)
For streaming sensor readings, a connection-oriented socket (Unix domain stream, or TCP) is obviously better, but then you also need to worry about the maximum number of connections allowed, and how to detect when the connection drops or the other end is too far behind. I personally like to use a separate thread for accepting new connections, passing them via a
queue to the request-response thread, and notifying the request-response thread via a pipe. I prefer asynchronous request-response handlers, based on
select or
selector, and non-blocking sockets.