Многопроцессорный питон внутри замороженного скрипта - PullRequest
10 голосов
/ 23 марта 2019

Я пытаюсь скомпилировать скрипт, использующий multiprocessing, в исполняемый файл Windows. Сначала я столкнулся с той же проблемой, что и Почему исполняемый файл Python открывает новый экземпляр окна, когда функция многопроцессорного модуля вызывается в Windows , когда я компилировал его в исполняемый файл. После принятого ответа я настроил свой сценарий так, чтобы

from multiprocessing import freeze_support
# my functions
if __name__ == "__main__":
    freeze_support()
    # my script

И это снова прекрасно работает, когда запускается как скрипт. Однако, когда я компилирую и запускаю его, я сталкиваюсь с:

Error message

Где я подчеркнул зеленой частью ошибки. Эта конкретная строка относится к

freeze_support()

в моем сценарии. Кроме того, на самом деле это не встречается в этой строке, но когда мой сценарий переходит к многопроцессорному, что-то вроде:

p = multiprocessing.Process(target=my_function, args=[my_list])
p.start()
p1 = multiprocessing.Process(target=my_function, args=[my_list])
p1.start()
p.join()
p1.join()

Это ошибка в многопроцессорном модуле (в частности, строка 148) или я неправильно понял ответ, который я связал, или что-то еще?

Я также отмечу, что сценарий работает правильно при компиляции, но вы должны нажать «ОК» в сообщении об ошибке для каждого многопроцессного процесса, который порождается (довольно много), и каждое сообщение об ошибке точно такое же. Означает ли это, что я неправильно завершаю процесс с p.join()?

Я также пробовал решение на Многопроцессорная обработка Python 3.4 не работает с py2exe , который рекомендует добавить

multiprocessing.set_executable(os.path.join(sys.exec_prefix, 'pythonw.exe'))

к вашему скрипту, но это приводит к ошибке в форме скрипта (даже не скомпилированной):

FileNotFoundError: [WinError 2] Системе не удается найти указанный файл

Спасибо за помощь!

документация freeze_support: https://docs.python.org/2/library/multiprocessing.html#multiprocessing.freeze_support

Ответы [ 2 ]

5 голосов
/ 26 марта 2019

Похоже, это было проблемой в течение достаточно долгого времени - я нашел ссылки, по крайней мере, начиная с 2014 года.Поскольку он кажется безвредным, общая рекомендация состоит в том, чтобы устранить ошибку, заменив sys.stdoutsys.stderr, который отображается на следующей строке), на фиктивную.Попробуйте это:

import os
import sys
from multiprocessing import freeze_support

if __name__ == '__main__':
    if sys.stdout is None:
        sys.stdout = sys.stderr = open(os.devnull, 'w')
    freeze_support()
3 голосов
/ 31 марта 2019

Это не проблема многопроцессорной библиотеки или py2exe как таковых, а побочный эффект от запуска приложения.Документация py2exe содержит некоторые обсуждения на эту тему:

Программа, работающая под Windows, может быть двух типов: консольная программа или программа для Windows.Консольная программа - это та, которая запускается в окне командной строки (cmd).Консольные программы взаимодействуют с пользователями по трем стандартным каналам: стандартный ввод, стандартный вывод и стандартная ошибка […].

В отличие от консольного приложения, оконное приложение взаимодействует с пользователем, используя сложный управляемый событиями пользовательский интерфейс.и поэтому не нуждается в стандартных каналах, использование которых в таких приложениях обычно приводит к сбою.

Py2exe в некоторых случаях автоматически решает эти проблемы, но по крайней мере один из ваших процессов не имеет прикрепленныхстандартный вывод: sys.stdout равен None), что означает, что sys.stdout.flush() равно None.flush(), что выдает ошибку, которую вы получаете.Приведенная выше документация имеет простое исправление, которое перенаправляет все выходные данные в файлы.

import sys
sys.stdout = open(“my_stdout.log”, “w”)
sys.stderr = open(“my_stderr.log”, “w”)

Просто добавьте эти строки в точку входа ваших процессов.Существует также соответствующая страница документации по взаимодействиям между Py2Exe и подпроцессами .

...