How to multithreaded / multiprocessor use only one instance of a specific function in Python?

I am running a Python script that controls a robot, but I'm a bit confused about how the multi-user engine control function is.

The problem is that the hardware is designed in such a way that the engines will not move unless there are several sleeping places in the engine control function, since the hardware takes time to send electrical signals to the engines. Because of these sleeping places in the engine control function, the entire program stops and stops reading the sensor data.

What I would like to do is to know how to multi-threaded / multiprocessor control the engine control function after calling it, but as soon as the program returns to the call in the next iteration of the cycle, it checks whether the engine control is still working (i.e. This is not done with sleep). If it is still running, it simply skips the engine control call and continues the cycle by reading the sensor data, and then checks again if the engine control function is working. Of course, if the engine control function no longer works, I would like it to be called again.

In principle, only two threads are required for the entire program: one that launches the main program, and one that branches and continuously restarts one instance of the engine control function each time the engine control function has completed its execution.

I tried to use concurrent.futures import, but received messages that it is not supported, and I could not find any use methods that I intend to use.

+4
source share
1 answer

I think you do not need threads, but I can misunderstand your requirements, so I will present 2 alternatives.

  • Without cutting and dreams

Assuming your current program runs like this:

while True: data = read_sensors() command = process(data) motor_do(command) time.sleep(delay) 

Then you can simply delete the dream and only call motor_do if the last call was at least delay seconds ago.

 last_call_time = -delay # to be sure that motor_do can be called the first time # "On Windows, [time.clock] returns wall-clock seconds elapsed since the first call to this # function, as a floating point number, based on the Win32 function QueryPerformanceCounter() # The resolution is typically better than one microsecond." (python 2.7 doc) # ie close to 0 on first call of time.clock() while True: data = read_sensors() command = process(data) motor_try(command) def motor_try(command): global last_call_time current_time = time.clock() # on win that works, on unix... you may want to take a look at the NB elapsed = current_time - last_call_time if elapsed >= delay: motor_do(command) last_call_time = current_time 
  1. With streaming processing (this is an example, I have no experience in streaming / asynchronous use with python 2.7, so there may be better ways to do this)

Assuming your current program runs like this:

 while True: data = read_sensors() command = process(data) motor_do(command) // this function sleeps and you CANNOT change it 

Then you need to start 1 thread, which will asynchronously invoke engine commands.

 import thread command = None command_lock = thread.allocate_lock() def main(): thread.start_new_thread(motor_thread) global command while True: data = read_sensors() with command_lock: command = process(data) def motor_thread(): while True: while not command: # just to be sure time.sleep(0.01) # small delay here (for instance, the time consumed by read_sensors + process) with command_lock: motor_do(command) command = None time.sleep(delay) 

NB: on Unix, time.clock() returns the processor time (= without downtime), so it would be better to use time.time() ... if the system clock is not changed: "Although this function usually returns non-decreasing values "it may return a lower value than the previous one if the system clock was set between two calls." (python 2.7 doc)

I do not know how time.sleep() reacts to changes in the system clock.

see How to get monotonous time durations in python? for exact time delays on unix / py2.7 (and Understanding time.perf_counter () and time.process_time () can be useful)

Python3: just use time.monotonic() ... or time.perf_counter() .

+1
source

All Articles