Python Forum
Watching for inputs from multiple sources concurrently - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/Forum-Python-Coding)
+--- Forum: General Coding Help (https://python-forum.io/Forum-General-Coding-Help)
+--- Thread: Watching for inputs from multiple sources concurrently (/Thread-Watching-for-inputs-from-multiple-sources-concurrently)



Watching for inputs from multiple sources concurrently - anakaine - Mar-03-2019

This is a question that I'm not sure how to begin answering - despite having written a few python scripts several thousand lines long, they've all been procedural - from one end to the other (spatial data manipulation), and despite some googling over the past few weeks with what I'm sure amounts to incorrect temrinology. The answer might be more conceptual than not - I'm not sure.

How would I go about watching for several inputs, each from different sources, at once?

If I'm on a raspberry pi, for example, I might like to be watching for a button press, input from another gpio source, incoming instructions from a network connection. On a PC I might wish to watch for incoming UDP packets whilst also allowing user input, etc.

Is there a particular strategy or method by which to watch for these things concurrently? Equally, is there some sort of terminology that would help me to find examples?


RE: Watching for inputs from multiple sources concurrently - Larz60+ - Mar-03-2019

There is a built-in driver that will monitor several GPIO pins and trigger events when any change
see: https://www.kernel.org/doc/Documentation/input/rotary-encoder.txt


RE: Watching for inputs from multiple sources concurrently - anakaine - Mar-03-2019

Thanks Larz, though that is not quite what I'm after.

I guess what I'm asking is - when I see example code it's always setting up for a particular job. Watch for an incoming UDP packet over network. Wait for an incoming IR signal. Wait for the user to press a button. Etc. Each of these things is always given in a function with a singular purpose - makes the code easy.

But what if I want the device to both wait for a UDP packet, and also keep an eye on an IR signal and wait on the button press (or any other types of inputs / stimulus). IS this a case for round robin checking of sensors? Then I think I'll probably miss half an IR signal, or miss the UDP packet, etc. Can I have multiple functions watching all at once?... Not sure. What would be the term to research to look at that?


RE: Watching for inputs from multiple sources concurrently - Larz60+ - Mar-03-2019

round robin is not good, wastes CPU time, and as you state, misses signals from time to time.
You're definitely looking for event (interrupt) driven software, but for any devise.
Something more in line with this: http://openbookproject.net/thinkcs/python/english3e/events.html


RE: Watching for inputs from multiple sources concurrently - woooee - Mar-03-2019

Quote:I want the device to both wait for a UDP packet, and also keep an eye on an IR signal
Multiprocessing is one way to do more than one thing at a time https://pymotw.com/3/multiprocessing/basics.html
Quote:and wait on the button press
Keep this in the program, i.e. not a separate process, as the program controls the terminal and input. A somewhat funky example from my toolbox that uses a Tkinter Button to terminate, and hopefully will help.
import tkinter as tk
import time
from multiprocessing import Process

class TestClass():
    def test_f(self, sleep_time=0.5):
        """ a simple counter function that simulates
            a separate process 
        """
        ctr = 0
        while True:
            print(ctr)
            ctr += 1
            time.sleep(sleep_time)

    def tk_quit(self):
        """ this function just waits for a button click and then
            exits/returns, allowing the rest of this program to execute
        """
        root=tk.Tk()
        tk.Button(root, text="Quit", command=root.quit,
                  width=10, bg="orange").grid()
        root.mainloop()

if __name__ == '__main__':
     ## run function in the background
     CT=TestClass()

     ## simulate 2 processes running different things
     ## start as many processes as you want
     p1=Process(target=CT.test_f)
     p1.start()
     p2=Process(target=CT.test_f, args=(0.75,))
     p2.start()

     CT.tk_quit()
     print("terminating processes")
     for p in [p1, p2]:
         if p.is_alive():
             p.terminate()
         p.join()