[英]Python multiprocessing.Pool: AttributeError
我在一个类中有一个方法需要在循环中做很多工作,我想把工作分散到我所有的核心上。
我编写了以下代码,如果我使用普通map()
,它会起作用,但是使用pool.map()
返回错误。
import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)
class OtherClass:
def run(sentence, graph):
return False
class SomeClass:
def __init__(self):
self.sentences = [["Some string"]]
self.graphs = ["string"]
def some_method(self):
other = OtherClass()
def single(params):
sentences, graph = params
return [other.run(sentence, graph) for sentence in sentences]
return list(pool.map(single, zip(self.sentences, self.graphs)))
SomeClass().some_method()
AttributeError: 无法腌制本地对象“SomeClass.some_method..single”
为什么它不能腌制single()
? 我什至尝试将single()
移动到全局模块范围(不在类内部 - 使其独立于上下文):
import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)
class OtherClass:
def run(sentence, graph):
return False
def single(params):
other = OtherClass()
sentences, graph = params
return [other.run(sentence, graph) for sentence in sentences]
class SomeClass:
def __init__(self):
self.sentences = [["Some string"]]
self.graphs = ["string"]
def some_method(self):
return list(pool.map(single, zip(self.sentences, self.graphs)))
SomeClass().some_method()
我得到以下...
AttributeError: 无法从“.../test.py”获取模块“ main ”上的属性“single”
AttributeError: 无法腌制本地对象“SomeClass.some_method..single”
您通过将嵌套的目标函数single()
移到顶层,自己解决了这个错误。
背景:
池需要腌制(序列化)它发送到其工作进程( IPC )的所有内容。 Pickling 实际上只保存函数的名称,而 unpickling 需要按名称重新导入函数。 为此,该函数需要在顶级定义,嵌套函数将无法被子项导入,并且已经尝试对它们进行腌制会引发异常( more )。
AttributeError: 无法从“.../test.py”获取模块“main”上的属性“single”
您在定义函数和类之前启动池,这样子进程就不能继承任何代码。 将您的池启动到底部并使用if __name__ == '__main__':
保护(为什么? )它if __name__ == '__main__':
import multiprocessing
class OtherClass:
def run(self, sentence, graph):
return False
def single(params):
other = OtherClass()
sentences, graph = params
return [other.run(sentence, graph) for sentence in sentences]
class SomeClass:
def __init__(self):
self.sentences = [["Some string"]]
self.graphs = ["string"]
def some_method(self):
return list(pool.map(single, zip(self.sentences, self.graphs)))
if __name__ == '__main__': # <- prevent RuntimeError for 'spawn'
# and 'forkserver' start_methods
with multiprocessing.Pool(multiprocessing.cpu_count() - 1) as pool:
print(SomeClass().some_method())
附录
...我想把工作分散到我所有的核心上。
关于multiprocessing.Pool
如何分块工作的潜在有用背景:
我无意中发现了一个非常讨厌的解决方案。 只要您使用def
语句,它就可以工作。 如果您声明要在Pool.map
使用的函数,并在解决它的函数的开头使用global
关键字。 但我不会在严肃的应用中依赖这个 😉
import multiprocessing
pool = multiprocessing.Pool(multiprocessing.cpu_count() - 1)
class OtherClass:
def run(sentence, graph):
return False
class SomeClass:
def __init__(self):
self.sentences = [["Some string"]]
self.graphs = ["string"]
def some_method(self):
global single # This is ugly, but does the trick XD
other = OtherClass()
def single(params):
sentences, graph = params
return [other.run(sentence, graph) for sentence in sentences]
return list(pool.map(single, zip(self.sentences, self.graphs)))
SomeClass().some_method()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.