我遇到以下格式的代码问题,并假设错误与我试图访问每个元组中的元素的方式有关。
from numberer import numberify
from sys import argv
infile=argv[1]
from multiprocessing import Pool
pool=Pool(15)
import os
def chunker(fob):
chunkbegin=0
filesize=os.stat(fob.name).st_size
while chunkbegin < filesize:
chunkend=chunkbegin+100000
fob.seek(chunkend)
fob.readline()
chunkend=fob.tell()
yield (chunkbegin,chunkend)
chunkbegin=chunkend
def run(tup, fob):
fob.seek(tup[0])
length=int(tup[1])-int(tup[0])
lines=fob.readlines(length)
for line in lines:
print(line)
fob=open(infile)
chunks=[x for x in chunker(fob)]
pool.map(run, (chunks, fob))
确切的错误是:
Process ForkPoolWorker-1:
Traceback (most recent call last):
File "/usr/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib/python3.6/multiprocessing/process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.6/multiprocessing/pool.py", line 108, in worker
task = get()
File "/usr/lib/python3.6/multiprocessing/queues.py", line 337, in get
return _ForkingPickler.loads(res)
AttributeError: Can't get attribute 'run' on <module '__main__' from 'pretonumber.py'>
1)所以当map函数将元组映射到函数时;我假设这些元素应该被称为普通元组? IE有一个索引吗?
2)我传递给函数run的元素块:是一个元组列表: chunks = [(0,100000),(100000,200000)....]由生成器chunker创建。
谢谢。
答案 0 :(得分:1)
map
方法采用可迭代的参数。 iterable的每个元素都传递给run
的一个实例。由于您的iterable是元组(chunks, fob)
,因此这将运行两个任务,在一个任务中调用run(chunks)
,在另一个任务中调用run(fob)
。
我认为您要做的是为chunk
中的每个chunks
运行一项任务,呼叫run(chunk, fob)
。
首先,您需要一个每个块一次产生(chunk, fob)
的迭代,例如((chunk, fob) for chunk in chunks)
。
但是这仍然不起作用,因为它将使用单个参数调用run
,即2元组(chunk, fob)
,而不是两个参数。您可以通过重写或包装run
来获取单个2元组而不是两个单独的参数来解决此问题,或者您可以使用starmap
代替map
,这样可以为您完成
但这仍然无法奏效。您尝试在进程之间传递打开的文件对象,multiprocessing
无法执行此操作。
由于你正在使用fork
方法,你有时可以从父级继承文件对象而不是传递它,但细节很复杂,你真的需要阅读{{3对于multiprocessing
并了解文件描述符继承如何在Unix上运行。
由于您希望每个孩子都拥有自己的文件对象的独立副本,因此他们可以在其中全部seek
,最简单的解决方案是只传递文件名并让它们自己open
:
def run(tup, path):
with open(path) as fob:
fob.seek(tup[0])
length=int(tup[1])-int(tup[0])
lines=fob.readlines(length)
for line in lines:
print(line)
fob = open(infile)
chunks = [x for x in chunker(fob)]
args = ((chunk, infile) for chunk in chunks)
pool.starmap(run, args)
与此同时,既然我们确信我们不依赖于fork
行为,那么编写代码以使用任何start方法可能是个好主意。这意味着将顶级代码放入__main__
块。而且,在我们处理它的时候,让我们确保一旦完成它就关闭文件:
# imports
# function definitions
if __name__ == '__main__':
infile = argv[1]
pool = Pool(15)
with open(infile) as fob:
chunks = [x for x in chunker(fob)]
args = ((chunk, infile) for chunk in chunks)
pool.starmap(run, args)
您的代码中可能仍有其他错误,但我认为这会耗尽multiprocessing
个错误。