Ошибка многопроцессорной библиотеки Python (AttributeError: __exit__)

Я получаю эту ошибку при использовании pool.map(funct, iterable):

AttributeError: __exit__

Без объяснения, только трассировка стека до файла pool.py в модуле.

используя таким образом:

with Pool(processes=2) as pool:
   pool.map(myFunction, mylist)
   pool.map(myfunction2, mylist2)

Я подозреваю, что может быть проблема с возможностью выбора (python должен pickle или преобразовать данные списка в поток байтов), но я не уверен, правда ли это или нужно отлаживать.

РЕДАКТИРОВАТЬ: новый формат кода, который вызывает эту ошибку:

def governingFunct(list):
    #some tasks
    def myFunction():
         # function contents
    with closing(Pool(processes=2)) as pool:
         pool.map(myFunction, sublist)
         pool.map(myFunction2, sublist2)

ПРОИЗВЕДЕНА ОШИБКА:

PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed

person sidewaiise    schedule 22.09.2014    source источник
comment
что вы имеете в виду под while .. as? ты имел ввиду with?   -  person Elisha    schedule 22.09.2014
comment
Включите полную трассировку для ошибок и ваш фактический код. while здесь, например, очевидная синтаксическая ошибка, но из исключения ясно, что вы действительно использовали with.   -  person Martijn Pieters    schedule 22.09.2014


Ответы (2)


В Python 2.x и 3.0, 3.1 и 3.2 объекты multiprocessing.Pool() не являются менеджерами контекста. Вы не можете использовать их в выражении with. Только в Python 3.3 и выше вы можете использовать их как таковые. Из документации Python 3 multiprocessing.Pool():

Новое в версии 3.3: объекты пула теперь поддерживают протокол управления контекстом - см. Типы диспетчера контекста. __enter__() возвращает объект пула, а __exit__() вызывает terminate ().

Для более ранних версий Python вы можете использовать contextlib.closing(), но примите во внимание, что это вызовет pool.close(), а не pool.terminate(). В этом случае завершите работу вручную:

from contextlib import closing

with closing(Pool(processes=2)) as pool:
    pool.map(myFunction, mylist)
    pool.map(myfunction2, mylist2)
    pool.terminate()

или создайте свой собственный terminating() диспетчер контекста:

from contextlib import contextmanager

@contextmanager
def terminating(thing):
    try:
        yield thing
    finally:
        thing.terminate()

with terminating(Pool(processes=2)) as pool:
    pool.map(myFunction, mylist)
    pool.map(myfunction2, mylist2)
person Martijn Pieters    schedule 22.09.2014
comment
Что ж, сэр, спасибо за такое подробное объяснение. Ваше решение приблизило функцию к работе - теперь я получаю эту ошибку: PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed - person sidewaiise; 22.09.2014
comment
@sidewaiise: возможно, вы пытаетесь использовать метод в классе? См. Многопроцессорность: использование Pool.map для функции, определенной в классе - person Martijn Pieters; 22.09.2014
comment
Хех, я как раз читал это, когда вы это писали. Спасибо - я скоро прочту и прокомментирую. - person sidewaiise; 22.09.2014
comment
Не уверен, что я понимаю решение по этой ссылке - я не использую классы. Это так же просто, как я писал выше, за исключением того, что он находится внутри другой функции .... например: **** См. Отредактированный вопрос ^ **** Так что не уверен ... есть идеи? - person sidewaiise; 22.09.2014
comment
@sidewaiise: функции, вложенные в другую функцию, не допускаются. Обычно pickle сохраняет только имя (modulename.functionname), а затем импортирует ту же функцию с другой стороны. Вы не можете этого сделать, если вам нужно вызвать другую функцию, чтобы получить функцию. - person Martijn Pieters; 22.09.2014
comment
Попадание туда ... новая ошибка: IndexError: string index out of range. Снова нет объяснения того, где на самом деле возникает ошибка. - person sidewaiise; 22.09.2014
comment
(Я также взял метод Pool из исходной функции) - person sidewaiise; 22.09.2014
comment
Если у вас возникли новые проблемы, лучше задайте новый вопрос. Ваша первоначальная проблема здесь все-таки решена, и теперь у нас есть хороший вопрос + ответ, на который, возможно, в будущем ответят другие. Не нужно путать это с новыми, разными проблемами. - person Martijn Pieters; 22.09.2014
comment
Истинный. На самом деле сделали только что, спасибо. stackoverflow.com/questions/25974256/ - person sidewaiise; 22.09.2014
comment
Извините, но когда я создаю свой терминатор, мне нужно делать from contextlib import contextmanager? - person paulochf; 14.05.2015
comment
@paulochf: по какой-то причине отсутствовала строка декоратора. Импортируйте его только тогда, когда вы действительно планируете его использовать! :-) (и извините). - person Martijn Pieters; 15.05.2015

Оператор with предназначен для объекта, который имеет функции __enter__ и __exit__, т.е. Типы диспетчера контекста
multiprocessing.Pool не является типом диспетчера контекста. попробуйте сделать следующее:

pool = Pool(processes=2)
pool.map(myFunction, mylist)
pool.map(myfunction2, mylist2)
person Elisha    schedule 22.09.2014
comment
Вопрос в том, почему ОП так подумал. Ответ в том, что в документации Python 3 сказано, что это так. Но он также квалифицирует это как Python 3.3 и выше. - person Martijn Pieters; 22.09.2014