如何解决Python多进程中的“AttributeError: __exit__”错误?
我尝试重写一些读取csv文件的代码,以便能够在Python 3.2.2中使用多个核心来运行。为了实现这一点,我使用了多进程中的Pool
对象,这个方法是我从一些有效的例子中改编过来的(而且在我项目的其他部分也成功过)。不过,我遇到了一个错误信息,感觉很难理解和排查。
错误信息:
Traceback (most recent call last):
File "parser5_nodots_parallel.py", line 256, in <module>
MG,ppl = csv2graph(r)
File "parser5_nodots_parallel.py", line 245, in csv2graph
node_chunks)
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/multiprocessing/pool.py", line 552, in get
raise self._value
AttributeError: __exit__
相关代码:
import csv
import time
import datetime
import re
from operator import itemgetter
from multiprocessing import Pool
import itertools
def chunks(l,n):
"""Divide a list of nodes `l` in `n` chunks"""
l_c = iter(l)
while 1:
x = tuple(itertools.islice(l_c,n))
if not x:
return
yield x
def csv2nodes(r):
strptime = time.strptime
mktime = time.mktime
l = []
ppl = set()
pattern = re.compile(r"""[A-Za-z0-9"/]+?(?=[,\n])""")
for row in r:
with pattern.findall(row) as f:
cell = int(f[3])
id = int(f[2])
st = mktime(strptime(f[0],'%d/%m/%Y'))
ed = mktime(strptime(f[1],'%d/%m/%Y'))
# collect list
l.append([(id,cell,{1:st,2: ed})])
# collect separate sets
ppl.add(id)
return (l,ppl)
def csv2graph(source):
MG=nx.MultiGraph()
# Remember that I use integers for edge attributes, to save space! Dic above.
# start: 1
# end: 2
p = Pool()
node_divisor = len(p._pool)
node_chunks = list(chunks(source,int(len(source)/int(node_divisor))))
num_chunks = len(node_chunks)
pedgelists = p.map(csv2nodes,
node_chunks)
ll = []
ppl = set()
for l in pedgelists:
ll.append(l[0])
ppl.update(l[1])
MG.add_edges_from(ll)
return (MG,ppl)
with open('/Users/laszlosandor/Dropbox/peers_prisons/python/codetenus_test.txt','r') as source:
r = source.readlines()
MG,ppl = csv2graph(r)
有什么好的方法来排查这个问题吗?
4 个回答
9
这个错误也会出现在你尝试使用
with multiprocessing.Pool() as pool:
# ...
时,如果你的Python版本太旧(比如Python 2.X),它就不支持将with
和多进程池一起使用。
(想了解更多细节,可以看看这个回答 https://stackoverflow.com/a/25968716/1426569)
66
在这个情况下,提问者并没有问题,但对于一般的“AttributeError: __exit__”错误,第一步的排查应该是检查括号是否写对了,比如:
with SomeContextManager() as foo:
#works because a new object is referenced...
不要
with SomeContextManager as foo:
#AttributeError because the class is referenced
我有时候也会被这个搞糊涂,最后还是得来这里找答案 -__-
162
问题出在这一行:
with pattern.findall(row) as f:
你在使用 with
语句。这个语句需要一个有 __enter__
和 __exit__
方法的对象。但是 pattern.findall
返回的是一个 list
(列表),而 with
试图去找 __exit__
方法,但找不到,所以就报错了。你只需要用
f = pattern.findall(row)
来代替。