2011-09-16 17 views
61

Intenté reescribir algún código de lectura de csv para poder ejecutarlo en múltiples núcleos en Python 3.2.2. Traté de usar el objeto Pool de multiprocesamiento, que adapté de ejemplos prácticos (y que ya funcionó para mí en otra parte de mi proyecto). Me encontré con un mensaje de error que me pareció difícil de descifrar y solucionar. ¿Cuál es una buena manera de solucionar esto? ¡Gracias!cómo solucionar un "AttributeError: __exit__" en multiproccesing en Python?

El error:

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__ 

El código relevante:

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

En mi caso, yo estaba pasando por error un 'None' debido al alcance cuestiones. – ThorSummoner

+0

Tuve esto cuando declaraba una clase como 'Clase SomeClass (object):' aunque EXPRESA explícitamente un __exit__ en mi clase. Una vez que eliminé la herencia de 'object' funcionó. No tengo idea por qué, así que YMMV – mpag

Respuesta

111

El problema está en esta línea:

with pattern.findall(row) as f: 

Está utilizando la sentencia with. Requiere un objeto con los métodos __enter__ y __exit__. Pero pattern.findall devuelve un list, with intenta almacenar el método __exit__, pero no puede encontrarlo y genera un error. Simplemente use

f = pattern.findall(row) 

en su lugar.

39

No es el problema del asker en este caso, pero el primer paso de solución de problemas para un "AttributeError: __exit__" genérico debe asegurarse de que los corchetes estén allí, p.

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

no

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

me pilla fuera de vez en cuando y me acaban aquí -__-

Cuestiones relacionadas