Comment dépanner une «AttributeError: __exit__» en multiproccesing en Python?

87

J'ai essayé de réécrire du code de lecture csv pour pouvoir l'exécuter sur plusieurs cœurs en Python 3.2.2. J'ai essayé d'utiliser l' Poolobjet de multiprocessing, que j'ai adapté à partir d'exemples de travail (et déjà travaillé pour moi pour une autre partie de mon projet). J'ai rencontré un message d'erreur que j'ai trouvé difficile à déchiffrer et à dépanner.

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 pertinent:

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)

Quelle est la bonne façon de résoudre ce problème?

László
la source
1
Dans mon cas, je passais accidentellement un en Noneraison de problèmes de portée.
ThorSummoner
J'avais ceci quand je déclarais une classe comme Class SomeClass(object):même si j'avais explicitement une sortie dans ma classe. Une fois que j'ai supprimé l'héritage, objectcela a fonctionné. Je ne sais pas pourquoi, alors YMMV
mpag

Réponses:

154

Le problème est dans cette ligne:

with pattern.findall(row) as f:

Vous utilisez la withdéclaration. Il nécessite un objet avec __enter__et des __exit__méthodes. Mais pattern.findallrenvoie a list, withessaie de stocker la __exit__méthode, mais il ne peut pas la trouver et génère une erreur. Juste utiliser

f = pattern.findall(row)

au lieu.

utdemir
la source
62

Ce n'est pas le problème du demandeur dans cette instance mais la première étape de dépannage pour un "AttributeError: __exit__" générique doit être de s'assurer que les crochets sont là, par exemple

with SomeContextManager() as foo:
    #works because a new object is referenced...

ne pas

with SomeContextManager as foo:
    #AttributeError because the class is referenced

Me surprend de temps en temps et je me retrouve ici -__-

Poches et
la source
9

L'erreur se produit également lorsque vous essayez 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 withavec des pools de multiprocesseur.

(Voir cette réponse https://stackoverflow.com/a/25968716/1426569 à une autre question pour plus de détails)

oseiskar
la source
Oui! Fonctionne très bien sur Python 3.X
Sreekant Shenoy
-1

La raison de cette erreur est la suivante: l'application Flask est déjà en cours d'exécution, ne s'est pas arrêtée et au milieu de cela, nous essayons de démarrer une autre instance par: avec app.app_context (): #Code Avant de l'utiliser avec une instruction, nous devons faire Assurez-vous que la portée de l'application précédente en cours d'exécution est fermée.

SIDDHARTH SETHIA
la source