某个项目,需要使用多进程以加快速度,之前一直没用过多进程,Pycharm可以跑,但需要在jupyter上运行,出现的问题是:程序一直在运行中,但是没有输出结果
① jupyter notebook/lab中直接使用多进程的话,虽然在界面上不会报错,但一直会处于运行状态,去查看命令行的话会看到报错: AttributeError: Can’t get attribute ‘XXX’ on <module ‘main’ >,由于某些原因Pool不能始终使用未在导入的模块中定义的对象。
根据上一篇博客中得到的一些知识点,实际上这个地方:在linux中使用的是fork的方式,可以复制公共变量和方法到新开启的进程中,但是windows中是重建一个新的进程(全新),在进程中并不存在公共的变量和方法,所以会出现这个问题,未能导入模块中定义的对象
② 运行时报错: AttributeError: module ‘main’ has no attribute ‘spec’,这时需要在if __name__ == __main__
:下面加上: spec = “ModuleSpec(name=‘builtins’, loader=<class ‘_frozen_importlib.BuiltinImporter’>)”
jupyter只能跟踪主进程,没法跟踪子进程,网上有一些其他的解决办法,但个人觉得最简单的还是将代码打包成py文件,再让jupyter执行这个文件
我基本上是在使用多处理模块,但我仍在学习多处理功能.我正在使用达斯蒂·菲利普斯(Dusty Phillips)编写的书,而这则代码属于该书.
import multiprocessing
import random
from multiprocessing.pool import Pool
def prime_factor(value):
factors = []
for divisor in range(2, value-1):
quotient, remainder = divmod(value, divisor)
if not remainder:
factors.extend(prime_factor(divisor))
factors.extend(prime_factor(quotient))
break
else:
factors = [value]
return factors
if __name__ == '__main__':
pool = Pool()
to_factor = [ random.randint(100000, 50000000) for i in range(20)]
results = pool.map(prime_factor, to_factor)
for value, factors in zip(to_factor, results):
print("The factors of {} are {}".format(value, factors))
复制代码
在Windows PowerShell上(不在jupyter笔记本上),我看到以下内容
Process SpawnPoolWorker-5:
Process SpawnPoolWorker-1:
AttributeError: Can't get attribute 'prime_factor' on <module '__main__' (built-in)>
复制代码
我不知道为什么该单元永远不会停止运行?
解决方案
在Jupyter笔记本电脑中,问题似乎与设计理念不同.因此,我们必须将函数(prime_factor)写入另一个文件,然后导入该模块.此外,我们必须注意调整.例如,就我而言,我已将该函数编码到一个名为defs.py
的文件中.
def prime_factor(value):
factors = []
for divisor in range(2, value-1):
quotient, remainder = divmod(value, divisor)
if not remainder:
factors.extend(prime_factor(divisor))
factors.extend(prime_factor(quotient))
break
else:
factors = [value]
return factors
复制代码
然后在jupyter笔记本中我写了以下几行
import multiprocessing
import random
from multiprocessing import Pool
import defs
if __name__ == '__main__':
pool = Pool()
to_factor = [ random.randint(100000, 50000000) for i in range(20)]
results = pool.map(defs.prime_factor, to_factor)
for value, factors in zip(to_factor, results):
print("The factors of {} are {}".format(value, factors))
复制代码
这解决了我的问题