Ik heb geprobeerd wat csv-leescode te herschrijven om het op meerdere kernen in Python 3.2.2 te kunnen uitvoeren. Ik heb geprobeerd het Pool
-object van multiprocessing te gebruiken, dat ik heb aangepast aan de hand van werkvoorbeelden (en al voor mij werkte voor een ander deel van mijn project). Ik kwam een foutmelding tegen die ik moeilijk kon ontcijferen en oplossen.
De fout:
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__
De relevante code:
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)
Wat is een goede manier om dit op te lossen?
Antwoord 1, autoriteit 100%
Het probleem zit in deze regel:
with pattern.findall(row) as f:
U gebruikt de with
-instructie. Het vereist een object met de methoden __enter__
en __exit__
. Maar pattern.findall
retourneert een list
, with
probeert de methode __exit__
op te slaan, maar kan het niet vinden het, en geeft een fout. Gebruik gewoon
f = pattern.findall(row)
in plaats daarvan.
Antwoord 2, autoriteit 41%
In dit geval is het niet het probleem van de vrager, maar de eerstestap voor probleemoplossing voor een generieke “AttributeError: __exit__” zou moeten zijn ervoor te zorgen dat de haakjes aanwezig zijn, bijvoorbeeld
with SomeContextManager() as foo:
#works because a new object is referenced...
niet
with SomeContextManager as foo:
#AttributeError because the class is referenced
Betrapt me af en toe en ik eindig hier -__-
Antwoord 3, autoriteit 6%
De fout treedt ook op bij het gebruik van de
with multiprocessing.Pool() as pool:
# ...
met een Python-versie die te oud is (zoals Python 2.X) en die het gebruik van with
samen met multiprocessing-pools niet ondersteunt.
(Zie dit antwoord https://stackoverflow.com/a/25968716/1426569op een andere vraag voor meer details )
Antwoord 4
De reden achter deze fout is:
Flask-app is al actief, is niet afgesloten en in het midden daarvan proberen we een andere instantie te starten door:
met app.app_context():
#Code
Voordat we dit met instructie gebruiken, moeten we ervoor zorgen dat het bereik van de vorige actieve app is gesloten.