ProcessPoolExecutor не может выполнять мои собственные функции, но выполняет печать
Код:
if __name__ == "__main__": p = ProcessPoolExecutor() p.submit(lambda x: print(x), "something") # doesn't work p.submit(print, "something") # works fine time.sleep(0.5)
Почему это имеет смысл?
9X_python-shell
Ответ #1
Ответ на вопрос: ProcessPoolExecutor не может выполнять мои собственные функции, но выполняет печать
ProcessPoolExecutor
хочет замариновать функцию, но поскольку 9X_py лямбда не имеет имени, ее нельзя найти для 9X_pythonista замаринования.
Например:
from pickle import dumps def fun(x): print(x) lmb = lambda x: print(x) dumps(fun) # succeeds dumps(lmb) # fails
Итак, это будет работать 9X_python нормально:
import time from concurrent.futures import ThreadPoolExecutor def fun(x): print(x) if __name__ == "__main__": p = ThreadPoolExecutor() lmb = lambda x: print(x) p.submit(lmb, "lambda") # works fine p.submit(fun, "local function") # works fine p.submit(print, "built-in function") # works fine time.sleep(0.5)
Но если вы замените ThreadPoolExecutor()
на ProcessPoolExecutor()
, который 9X_pythonic должен будет замариновать функцию, лямбда 9X_python-shell перестанет работать.
from concurrent.futures import ProcessPoolExecutor if __name__ == "__main__": p = ProcessPoolExecutor() lmb = lambda x: print(x) future = p.submit(lmb, "lambda") # doesn't work print(future.result())
Это показывает, что 9X_python проблема действительно возникает при травлении, а 9X_pythonic также объясняет, почему:
_pickle.PicklingError: Can't pickle at 0x00000294E66B3E20>: attribute lookup on __main__ failed
__main__
— это основной 9X_python-shell процесс, в пространстве имен которого нет 9X_python-interpreter лямбды, потому что сама лямбда безымянна. Присвоение 9X_py его переменной типа lmb
не меняет этого, поскольку 9X_python-multiprocessing лямбда разыменовывается из переменной. Две 9X_py другие функции по своей сути имеют имена 9X_python-interpreter в пространстве имен __main__
и могут быть замаринованы.
Обратите 9X_python-shell внимание, что __main__
— это то же имя, которое 9X_pythonic вы бы проверили в:
if __name__ == "__main__":
Ответ #2
Ответ на вопрос: ProcessPoolExecutor не может выполнять мои собственные функции, но выполняет печать
Если вы проверите result будущего, вы увидите 9X_python-shell соответствующее сообщение об ошибке:
>>> from concurrent.futures import ProcessPoolExecutor >>> p = ProcessPoolExecutor() >>> p.submit(lambda x: print(x), "something").result() ... PicklingError: Can't pickle at 0x113eec5e0>: attribute lookup on __main__ failed
Таким 9X_python-multiprocessing образом, это сообщение об ошибке говорит 9X_python само за себя, если вы знакомы с тем, как 9X_pythonista работает исполнитель пула процессов. Но 9X_pythonista если это не так, то может потребоваться 9X_python-multiprocessing дополнительное объяснение: процесс попытается 9X_python-multiprocessing получить доступ к рабочей функции по имени, но, поскольку 9X_python лямбда-функции являются "анонимными" функциями, у 9X_python-multiprocessing них нет допустимого имени для поиска в модуле. пространство 9X_py имен.
>>> (lambda x: print(x)).__name__ ''
В качестве обходного пути вы можете 9X_pythonista использовать многопроцессорный пул pathos, который 9X_python использует dill, более мощную библиотеку сериализации, чем 9X_pythonic pickle. В отличие от pickle, укроп может сериализовать 9X_python-multiprocessing лямбда-выражения. Пафосный интерфейс ProcessPool
немного 9X_python-multiprocessing отличается от многопроцессорной обработки 9X_python stdlib ProcessPoolExecutor
, но ближайшей аналогией с вашим 9X_pythonista простым использованием submit
будет pipe
:
>>> from pathos.multiprocessing import ProcessPool >>> p = ProcessPool() >>> p.pipe(lambda x: print(x), "something") something
Если вам 9X_pythonic интересно, как укроп может сбрасывать лямбды, включите 9X_python-interpreter трассировку и посмотрите, что он на самом 9X_python деле делает с помощью этого фрагмента:
import dill.detect dill.detect.trace(True) dill.dumps(lambda x: print(x))
-
4
-
5
-
4
-
8
-
2
-
11
-
2
-
1
-
2
-
3
-
2
-
1
-
1
-
3
-
1
-
2
-
1
-
2
-
1
-
2
-
1
-
1
-
4
-
2
-
3
-
1
-
1
-
1
-
1
-
2
-
1
-
1
-
2
-
1
-
2
-
1
-
1
-
3
-
1
-
1
-
3
-
3
-
2
-
2
-
1
-
3
-
1
-
1
-
3
-
1