Làm cách nào để khắc phục sự cố “AttributeError: __exit__” trong đa quy trình bằng Python?


87

Tôi đã cố gắng viết lại một số mã đọc csv để có thể chạy nó trên nhiều lõi trong Python 3.2.2. Tôi đã cố gắng sử dụng Poolđối tượng đa xử lý, đối tượng mà tôi đã điều chỉnh từ các ví dụ làm việc (và đã làm việc cho tôi cho một phần khác của dự án của tôi). Tôi gặp phải thông báo lỗi mà tôi thấy khó giải mã và khắc phục sự cố.

Lỗi:

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__

Mã liên quan:

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)

Cách tốt để khắc phục sự cố này là gì?


1
Trong trường hợp của tôi, tôi đã vô tình vượt qua một Nonedo các vấn đề về phạm vi.
ThorSummoner

Tôi đã có điều này khi tôi khai báo một lớp Class SomeClass(object):mặc dù tôi đã DID rõ ràng có một lối ra trong lớp của mình. Một khi tôi loại bỏ thừa kế từ objectnó đã hoạt động. Tôi không biết tại sao, do đó, YMMV
MPAG

Câu trả lời:


154

Vấn đề là ở dòng này:

with pattern.findall(row) as f:

Bạn đang sử dụng withcâu lệnh. Nó yêu cầu một đối tượng với __enter____exit__các phương thức. Nhưng pattern.findalltrả về a list, withcố gắng lưu trữ __exit__phương thức, nhưng nó không thể tìm thấy nó và gây ra lỗi. Chỉ dùng

f = pattern.findall(row)

thay thế.


62

Đây không phải là vấn đề của người hỏi trong trường hợp này mà bước khắc phục sự cố đầu tiên đối với "AttributeError: __exit__" chung chung phải đảm bảo rằng dấu ngoặc ở đó, ví dụ:

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

không phải

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

Thỉnh thoảng theo dõi tôi và tôi kết thúc ở đây -__-


9

Lỗi cũng xảy ra khi cố gắng sử dụng

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

với phiên bản Python quá cũ (như Python 2.X) và không hỗ trợ sử dụng withcùng với các nhóm đa xử lý.

(Xem câu trả lời này https://stackoverflow.com/a/25968716/1426569 cho một câu hỏi khác để biết thêm chi tiết)


Vâng! Làm việc tuyệt vời trên Python 3.X
Sreekant Shenoy

-1

Lý do đằng sau lỗi này là: Ứng dụng Flask đã chạy, chưa tắt và giữa lúc đó, chúng tôi cố gắng khởi động một phiên bản khác bằng cách: with app.app_context (): #Code Trước khi sử dụng câu lệnh này với câu lệnh, chúng tôi cần thực hiện đảm bảo rằng phạm vi của ứng dụng đang chạy trước đó đã bị đóng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.