Python多处理竞争条件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python多处理竞争条件相关的知识,希望对你有一定的参考价值。

当我使用concurrent.futures从多个文本文件中读取时,我发现了一个奇怪的错误。

这是一个可重复的小例子:

import os
import concurrent.futures

def read_file(file):
    with open(os.path.join(data_dir, file),buffering=1000) as f:
        for row in f:
            try:
                print(row)
            except Exception as e:
                print(str(e))

if __name__ == '__main__':
    data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data'))
    files = ['file1', 'file2']
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for file,_ in zip(files,executor.map(read_file,files)):
            pass    

file1file2data目录中的任意文本文件。

我收到以下错误(基本上一个进程尝试在分配之前读取data_dir变量):

concurrent.futures.process._RemoteTraceback:
"""
Traceback (most recent call last):
  File "C:Usersmy_usernameAppDataLocalContinuumAnaconda3libconcurrentfuturesprocess.py", line 175, in _process_worker
    r = call_item.fn(*call_item.args, **call_item.kwargs)
  File "C:Usersmy_usernameAppDataLocalContinuumAnaconda3libconcurrentfuturesprocess.py", line 153, in _process_chunk
    return [fn(*args) for args in chunk]
  File "C:Usersmy_usernameAppDataLocalContinuumAnaconda3libconcurrentfuturesprocess.py", line 153, in <listcomp>
    return [fn(*args) for args in chunk]
  File "C:Usersmy_usernameDownloadsexample.py", line 5, in read_file
    with open(os.path.join(data_dir, file),buffering=1000) as f:
NameError: name 'data_dir' is not defined
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "example.py", line 16, in <module>
    for file,_ in zip(files,executor.map(read_file,files)):
  File "C:Usersmy_usernameAppDataLocalContinuumAnaconda3libconcurrentfutures\_base.py", line 556, in result_iterator
    yield future.result()
  File "C:Usersmy_usernameAppDataLocalContinuumAnaconda3libconcurrentfutures\_base.py", line 405, in result
    return self.__get_result()
  File "C:Usersmy_usernameAppDataLocalContinuumAnaconda3libconcurrentfutures\_base.py", line 357, in __get_result
    raise self._exception
NameError: name 'data_dir' is not defined

如果我在data_dir块之前放置if __name__ == '__main__':赋值,我不会收到此错误并且代码按预期执行。

导致此错误的原因是什么?显然,在两种情况下都应该进行任何异步调用之前分配data_dir

答案

fork()在windows上不可用,所以python使用spawn启动新进程,这将启动一个新的python解释器进程,没有内存将被共享,但python将在新进程中try to recreate worker函数环境,这就是为什么模块级变量有效。见doc for more detail

另一答案

ProcessPoolExecutor产生一个新的Python进程,导入正确的模块并调用您提供的功能。由于data_dir仅在运行模块时定义,而不是在导入模块时定义,因此可能会出现错误。

提供data_dir文件描述符作为read_file的参数可能有效,因为我相信进程继承了父进程的文件描述符。但是你需要检查一下。

但是,如果要使用ThreadPoolExecutor,那么您的示例应该可以工作,因为生成的线程共享内存。

以上是关于Python多处理竞争条件的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 viewpager 的异步任务时的竞争条件

Java代码竞争条件多线程?

如何使此 Java 代码正常运行? [多线程,竞争条件]

如何可靠地重现此 python 代码中的竞争条件?

常用python日期日志获取内容循环的代码片段

多线程和模板化单例竞争条件