2011-09-16 12 views
61

Ho provato a riscrivere un codice di lettura csv per poterlo eseguire su più core in Python 3.2.2. Ho provato a utilizzare l'oggetto Pool di multiprocessing, che ho adattato da esempi di lavoro (e già ha funzionato per me per un'altra parte del mio progetto). Ho trovato un messaggio di errore che ho trovato difficile da decifrare e risolvere. Qual è un buon modo per risolvere questo? Grazie!come risolvere un "AttributeError: __exit__" in multiproccesing in Python?

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

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) 
+1

Nel mio caso, ero di passaggio accidentalmente un 'none' a causa di scoping problemi. – ThorSummoner

+0

Ho avuto questo quando stavo dichiarando una classe come 'Class SomeClass (oggetto):' anche se ho DIH esplicitamente un __exit__ nella mia classe. Una volta rimossa l'ereditarietà da 'object' ha funzionato. Non ho idea del perché, quindi YMMV – mpag

risposta

111

Il problema è in questa linea:

with pattern.findall(row) as f: 

Si utilizza l'istruzione with. Richiede un oggetto con i metodi __enter__ e __exit__. Ma pattern.findall restituisce un list, with tenta di memorizzare il metodo __exit__, ma non riesce a trovarlo e genera un errore. Basta usare

f = pattern.findall(row) 

invece.

39

In questo caso, non è il problema del richiedente, ma il primo passo di risoluzione di per un errore "AttributeError: __exit__" generico deve essere assicurato che le parentesi siano presenti, ad esempio il .

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

non

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

catture Me Out di volta in volta e sono finito qui -__-

Problemi correlati