我应该是一个“令人尴尬的并行”任务:我正在尝试以CPU重的方式解析许多日志文件。我不关心他们完成的顺序,并且流程不需要共享任何资源或线程。
我在Windows机器上。
我的设置类似于:
main.py
import parse_file
import multiprocessing
...
files_list = ['c:\file1.log','c:\file2.log']
if __name__ == '__main__':
pool = multiprocessing.Pool(None)
for this_file in files_list:
r = pool.apply_async(parse_file.parse, (this_file, parser_config))
results = r.get()
...
#Code to do stuff with the results
parse_file
基本上是一个完全独立的模块,不访问任何共享资源 - 结果以列表形式返回。
当我在没有多处理的情况下运行它时,这一切都运行得非常好,但是当我启用它时,会发生什么事情,我得到一个巨大的错误墙,表明源模块(进入的模块)就是那个平行奔跑。 (错误是仅在源脚本(而不是parse_file模块)中的某个内容的数据库锁定错误,以及在多处理内容之前的某个点!)
我并不是假装理解多处理模块,而是使用other示例here,但没有一个包含任何表明这是正常的或者为什么会发生这种情况。
我做错了什么?如何多任务处理此任务? 谢谢!
使用此功能可轻松复制: test.py
import multiprocessing
import test_victim
files_list = ['c:\file1.log','c:\file2.log']
print("Hello World")
if __name__ == '__main__':
pool = multiprocessing.Pool(None)
results = []
for this_file in files_list:
r = pool.map_async(test_victim.calculate, range(10), callback=results.append)
results = r.get()
print(results)
test_victim.py:
def calculate(value):
return value * 10
运行test.py时的输出应为:
Hello World
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
但实际上它是:
Hello World
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
Hello World
Hello World
(额外的“Hello World”的实际数量)每次在1到4之间运行时都会改变=应该没有)
答案 0 :(得分:1)
在Windows上,当Python执行时
pool = multiprocessing.Pool(None)
产生了新的Python进程。由于Windows没有os.fork
,因此这些新的Python进程会重新导入调用模块。因此,任何不在里面的东西
if __name__ == '__main__':
为每个生成的进程执行一次。这就是为什么你会看到多个Hello Worlds
。
请务必阅读文档中的"Safe importing of main module"警告。
所以要修复,将所有需要在
中只需运行一次的代码if __name__ == '__main__':
语句。
例如,您的可运行示例将通过放置
来修复print("Hello World")
在if __name__ == '__main__'
语句中:
import multiprocessing
import test_victim
files_list = ['c:\file1.log','c:\file2.log']
def main():
print("Hello World")
pool = multiprocessing.Pool(None)
results = []
for this_file in files_list:
r = pool.map_async(test_victim.calculate, range(10), callback=results.append)
results = r.get()
print(results)
if __name__ == '__main__':
main()
产量
Hello World
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
特别是在Windows上,使用multiprocessing
的脚本必须既可以运行(作为脚本)又可以导入。使脚本可导入的简单方法是如上所示构造它。放置脚本应在名为main
的函数中执行的所有内容,然后使用
if __name__ == '__main__':
main()
在脚本的末尾。 main
之前的东西应该只是import语句和全局常量的定义。