首页 > 解决方案 > Python中多线程调用的问题

问题描述

我有一个脚本,它有两个线程,一个运行这个目标函数的工作线程:

def worker_thread_function():
    print(f'Worker thread started.')
    while self._keep_running:
        try:
            task = worker_queue.get(timeout=5)
            task() # I expect to be callables.
            worker_queue.task_done() # See https://docs.python.org/3/library/queue.html
        except queue.Empty:
            continue
    print(f'Worker thread finished.')

whereworker_queue是一个全局对象,其他“管理线程”在其中放置必须完成的工作。另一个线程以这种方式定期将内容放入此队列中:

def other_thread_function():
    while True:
        time.sleep(1)
        for device_name in devices_df.index: # Initialize this by logging once each device.
            if has_to_be_logged(device_name):
                print(f'Now queueing for log {device_name}')
                worker_queue.put(lambda: log_single_device_standby_IV(device_name))

并且该功能log_single_device_standby_IV使用该设备名称进行处理。我面临的问题是device_name排队任务时值正确,但任务完成时值错误。log_single_device_standby_IV如果我在这样的内部打印:

def log_single_device_standby_IV(device_name)
    print(f'log_single_device_standby_IV({device_name})')
    # do the stuff...

在我的输出中,我看到了这个:

Now queueing for log num5
log_single_device_standby_IV(num7) was called.
Now queueing for log num11
log_single_device_standby_IV(num7) was called.
Now queueing for log num5
log_single_device_standby_IV(num7) was called.

即它以某种方式改变了任何价值device_namenum7该设备num7随便是中的最后一个devices_df.index,不知道这是否可以提供任何提示。如果我像这样对设备名称进行硬编码:

def other_thread_function():
    while True:
        time.sleep(1)
        for device_name in devices_df.index: # Initialize this by logging once each device.
            if has_to_be_logged(device_name):
                worker_queue.put(lambda: log_single_device_standby_IV('num4'))

它工作正常,即它num4用作设备名称。

这里有什么问题?我不知道这是否与拥有多个线程、lambda 函数或什么有关...

标签: pythonmultithreadinglambda

解决方案


在问了这个问题并花了相当多的时间认为这是一个与线程相关的问题之后,我发现问题出在 lambda 函数上。使用 lambda 函数将行更改为

worker_queue.put(lambda dev=device_name: self.log_single_device_standby_IV(dev))

解决问题。

所以问题是 lambda 函数不是存储它的值device_name而是对它的引用。


推荐阅读