简体   繁体   English

如何在Python中多线程/多处理一个特定函数的一个实例?

[英]How to multithread/multiprocess just one instance of a particular function in Python?

I'm running a Python script that controls a robot, but I'm a bit confounded as to how to multithread the motor control function. 我正在运行一个控制机器人的Python脚本,但我对如何多线程控制电机控制功能感到困惑。

The issue is that the hardware is designed such that the motors won't move unless there are several sleeps in the motor-control function, because the hardware requires time to send the electrical signals to the motors. 问题在于硬件的设计使得电机不会移动,除非电机控制功能中存在多个休眠,因为硬件需要时间将电信号发送到电机。 Because of these sleeps in the motor-control function, the entire program halts and stops reading in sensor data. 由于电机控制功能中的这些休眠,整个程序停止并停止读取传感器数据。

What I would like to do is know how to multithread/multiprocess the motor-control function once it is called, but once the program hits the call again in the following iteration of the loop, it checks if the motor-control is still running (ie it isn't done with the sleep). 我想做的是知道如何在调用电机控制功能后对其进行多线程/多处理,但是一旦程序在循环的下一次迭代中再次遇到调用,它会检查电机控制是否仍在运行(即睡眠没有完成。 If it is still running, it simply skips over the motor-control call and continues on with looping, reading sensor data, and then checking again if the motor-control function is still running. 如果它仍在运行,它只是跳过电机控制调用并继续循环,读取传感器数据,然后再次检查电机控制功能是否仍在运行。 Of course, if the motor-control function is no longer running, I would like for it to once again be called. 当然,如果电机控制功能不再运行,我希望再次调用它。

Basically, the whole program only requires two threads: one that runs the main program, and one that branches off and continuously re-runs one instance of the motor-control function every time the motor-control function has completed its execution. 基本上,整个程序只需要两个线程:一个运行主程序,一个分支关闭,并在每次电机控制功能完成执行时连续重新运行一个电机控制功能实例。

I had tried using the concurrent.futures import but got messages saying it was not supported and I couldn't find any usages particular to the way I intend to use it. 我曾尝试使用concurrent.futures导入,但得到消息说它不受支持,我找不到任何特定于我打算使用它的方式的用法。

I think you don't need threading, but I may misunderstand your requirements so I will present 2 alternatives. 我认为你不需要线程,但我可能会误解你的要求,所以我将提出2个替代方案。

  1. Without threading and sleeps 没有线程和睡眠

Assuming your current program flows like that : 假设您当前的程序流程如下:

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

Then you could just remove the sleep, and only call motor_do if the last call was at least delay seconds ago. 然后你可以删除睡眠,如果最后一次呼叫至少delay几秒钟,则只调用motor_do。

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)
# i.e. 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 threading (this is an example, I have no experience in threading/async with python 2.7 so there may be better ways to do this) 使用线程(这是一个例子,我没有使用python 2.7进行线程/异步的经验,因此可能有更好的方法来执行此操作)

Assuming your current program flows like that : 假设您当前的程序流程如下:

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

Then you have to launch 1 thread that will only push the commands to the motor, asynchronously. 然后你必须启动1个线程,它只会异步地将命令推送到电机。

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 processor time (= without the idling time), so it would be better to use time.time() ... unless the system clock is changed : "While this function normally returns non-decreasing values, it can return a lower value than a previous call if the system clock has been set back between the two calls." 注意:在Unix上, time.clock()返回处理器时间(=没有空闲时间),所以最好使用time.time() ...除非更改系统时钟:“此函数通常返回非 - 如果在两次调用之间设置了系统时钟,则它可以返回比前一次调用更低的值。“ (python 2.7 doc) (python 2.7 doc)

I don't know how time.sleep() react to system clock changes. 我不知道time.sleep()对系统时钟变化的反应。

see How do I get monotonic time durations in python? 请参阅如何在python中获得单调持续时间? for precise time delays on unix/py2.7 (and Understanding time.perf_counter() and time.process_time() can be useful) 对于unix / py2.7上的精确时间延迟(以及了解time.perf_counter()和time.process_time()可能很有用)

Python3 : just use time.monotonic() ... or time.perf_counter() . Python3:只使用time.monotonic() ...或time.perf_counter()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM