J'ai essayé de réécrire du code de lecture csv pour pouvoir l'exécuter sur plusieurs cœurs dans Python 3.2.2. J'ai essayé d'utiliser l'objet Pool
du multitraitement, que je adapté d'exemples de travail (et déjà travaillé pour moi pour une autre partie de mon projet). Je suis tombé sur un message d'erreur que j'ai eu du mal à déchiffrer et à résoudre.
L'erreur:
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__
Le code correspondant:
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)
Quel est un bon moyen de résoudre ce problème?
Le problème est dans cette ligne:
with pattern.findall(row) as f:
Vous utilisez l'instruction with
. Il nécessite un objet avec __enter__
et __exit__
méthodes. Mais pattern.findall
retourne un list
, with
tente de stocker le __exit__
, mais il ne le trouve pas et génère une erreur. Juste utiliser
f = pattern.findall(row)
au lieu.
Dans ce cas, ce n’est pas le problème du demandeur, mais le premier étape de dépannage pour un "AttributeError: __exit__" générique doit vérifier que les crochets sont présents, par exemple.
with SomeEnterExitObject() as foo:
#works because a new object is referenced...
pas
with SomeEnterExitObject as foo:
#AttributeError because the class is referenced
Me surprend de temps en temps et je finis ici -__-
L’erreur se produit également lorsqu’on essaie d’utiliser le
with multiprocessing.Pool() as pool:
# ...
avec une version Python trop ancienne (comme Python 2.X) et ne prenant pas en charge l’utilisation de with
avec des pools de multitraitement.).
(Voir cette réponse https://stackoverflow.com/a/25968716/1426569 à une autre question pour plus de détails)
La raison de cette erreur est la suivante: Flask app est déjà en cours d'exécution, n'est pas arrêté et au milieu de cela, nous essayons de démarrer une autre instance avec: avec app.app_context (): #Code Before nous utilisons cette déclaration avec nous devons nous assurer que la portée de la précédente application en cours d'exécution est fermée.