Come risolvere un "AttributeError: __exit__" in multiproccesing in Python?


87

Ho provato a riscrivere del codice di lettura CSV per poterlo eseguire su più core in Python 3.2.2. Ho provato a utilizzare l' Poologgetto del multiprocessing, che ho adattato da esempi di lavoro (e già lavorato per me per un'altra parte del mio progetto). Mi sono imbattuto in un messaggio di errore che ho trovato difficile da decifrare e risolvere.

L'errore:

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__

Il codice pertinente:

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)

Qual è un buon modo per risolvere questo problema?


1
Nel mio caso, ho passato accidentalmente una a Nonecausa di problemi di scoping.
ThorSummoner

Ho avuto questo quando stavo dichiarando una classe come Class SomeClass(object):anche se avessi esplicitamente un'uscita nella mia classe. Una volta che ho rimosso l'eredità da objectesso ha funzionato. Non ho idea del perché, quindi
YMMV

Risposte:


155

Il problema è in questa linea:

with pattern.findall(row) as f:

Stai usando la withdichiarazione. Richiede un oggetto con metodi __enter__e __exit__. Mapattern.findall restituisce un list, withprova a memorizzare il __exit__metodo, ma non riesce a trovarlo e genera un errore. Basta usare

f = pattern.findall(row)

anziché.


63

Non è il problema del richiedente in questo caso, ma il primo passaggio per la risoluzione dei problemi per un generico "AttributeError: __exit__" dovrebbe essere quello di assicurarsi che le parentesi siano lì, ad es.

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

non

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

Mi prende di tanto in tanto e finisco qui -__-


9

L'errore si verifica anche quando si tenta di utilizzare il file

with multiprocessing.Pool() as pool:
   # ...

con una versione di Python che è troppo vecchia (come Python 2.X) e non supporta l'utilizzo withinsieme a pool multiprocessing.

(Vedi questa risposta https://stackoverflow.com/a/25968716/1426569 a un'altra domanda per maggiori dettagli)


Sì! Funziona alla grande su Python 3.X
Sreekant Shenoy,

-1

Il motivo di questo errore è: l'app Flask è già in esecuzione, non si è arrestata e nel mezzo proviamo ad avviare un'altra istanza: with app.app_context (): #Code Prima di usarlo con l'istruzione che dobbiamo fare assicurati che l'ambito della precedente app in esecuzione sia chiuso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.