#python #python_3x
Открываю документацию по модулю, копирую второй пример в IDE: from multiprocessing import Process def f(name): print('hello', name) if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() И получаю вот такой результат: >>> Traceback (most recent call last): File "", line 1, in File "C:\Python36\lib\multiprocessing\spawn.py", line 105, in spawn_main exitcode = _main(fd) File "C:\Python36\lib\multiprocessing\spawn.py", line 115, in _main self = reduction.pickle.load(from_parent) AttributeError: Can't get attribute 'f' on Тоже самое происходит и в стандартной IDLE, подскажите в чем может быть проблема? нашел частичное решение, если вместо multiprocessing использовать multiprocessing.dummy, то кое-что работает, однако все-равно не ясно из за чего это происходит
Ответы
Ответ 1
Модуль со скриптом (который процессы создаёт) обязан безопасно импортироваться без запуска новых процессов при использовании spawn (по умолчанию на Windows), forkserver методов запуска. См. пример в документации: Safe importing of main module. Обычно, достаточно if __name__ == '__main__' защиту использовать для частей, которые новые процессы создают. В интерактивном интерпретаторе и в модулях, которые как скрипты выполняются: __name__ == '__main__', поэтому могут ошибки возникать. Когда вы успешно импортируете f из другого модуля, он не будет назван __main__, поэтому может не возникнуть ошибка (успешный pickle). Подробнее: для запуска нового процесса, вам нужна функция f чтобы запустить функцию f, Питон должен импортировать модуль её содержащий. В новом процессе у вас ничего нет, кроме встроенных имён. Всё остальное явно импортируется если модуль назван __main__ (скрипт или интерактивный случай), то при импорте if __name__ == '__main__' выполняется и вы пытаетесь рекурсивно ещё новые процессы запустить (fork bomb). В реализации multiprocessing могут некоторые ухищрения присутствовать, чтобы вместо fork bomb исключение возникло (лучше) если модуль не назван __main__, то нет проблем с его импортом. В зависимости от особенностей реализации multiprocessing, текущего окружения, может быть достаточно, если f является pickable (глобальная функция из модуля, который можно импортировать, попадает в эту категорию) multiprocessing.dummy может работать так как в этом случае создаются новые потоки, а не процессы (все данные общие: глобальная переменная f во всех потоках доступна).Ответ 2
Для понимания, может вот такой пример поможет: from multiprocessing import Process from time import sleep class A: def __call__(self, count=10, sleep_time=0.5): for i in range(count): print('Working class A, i=%s' % i) sleep(sleep_time) class B: def __call__(self, count=10, sleep_time=0.5): for i in range(count): print('Working class B, i=%s' % i) sleep(sleep_time) if __name__ == '__main__': a = A() b = B() p1 = Process(target=a, kwargs={'sleep_time': 0.7}) p2 = Process(target=b, args=(12,)) p1.start() p2.start() p1.join() p2.join()Ответ 3
Как ни странно, работает, если разнести пример в два модуля: example1.py def f(name): print('hello', name) example2.py from multiprocessing import Process from example1 import * if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() Внес изменения, спасибо за уточнение в коментах.
Комментариев нет:
Отправить комментарий