Многопроцессорность запускает новые экземпляры главного окна, когда оно заморожено как исполняемый файл.

Я уже задавал этот точный вопрос год назад. В моем приложении используется многопроцессорный модуль Python, который отлично работает при запуске из командной строки, но когда я упаковываю его как исполняемый файл с помощью Pyinstaller, несколько процессов появляются как новые экземпляры оригинала, а не запускают функцию, которую они должны запускать. Совет, данный мне в прошлый раз, а также везде, где я смотрю, состоит в том, чтобы вызывать multiprocessing.freeze_support() в начале моего блока if __name__ == "__main__":, что я и делал все это время, но вдруг снова сталкиваюсь с этой проблемой по какой-то причине. Что еще может быть причиной этого?

Обновление: я подтвердил, что наличие строки freeze_support() никак не влияет на эту проблему. Комментирование или раскомментирование дает точно такое же поведение: копии главного окна открываются и ничего не делают. Вот блок, где он вызывается, в самом конце моего основного модуля Python:

if __name__ == '__main__':
    freeze_support()

    # (A bunch of commented-out lines)
    main()

person dpitch40    schedule 03.08.2012    source источник


Ответы (3)


Я идиот. (Ну, может быть, нет, но это была полностью моя вина) многопроцессорность сигнализирует процессу, что он является дочерним процессом, запуская его с двумя дополнительными аргументами: флагом --multiprocessing-fork и числовым дескриптором канала из родительского процесса. multiprocessing.freeze_support проверяет наличие этого флага, чтобы решить, запускать ли функцию, указанную для дочернего процесса, или обычную программу. Так или иначе, мой метод анализа аргументов командной строки изменил sys.argv, что избавило от флага и заставило дочерние процессы вести себя как новые родительские процессы.

Итак, мораль этой истории такова: никогда не изменяйте sys.argv. Я переключился на использование optparse, который жалуется на наличие флага, поэтому мне пришлось передать ему отфильтрованный список аргументов. Как только я это сделал, проблема исчезла.

person dpitch40    schedule 06.08.2012
comment
Привет, у меня все еще есть эта проблема, но я даже не касаюсь sys.argv в своем сценарии. Можете ли вы направить какие-либо ссылки, чтобы я мог исследовать, почему он это делает? - person hpca01; 12.09.2018

У меня была та же проблема, но я решил добавить в код предложения if, чтобы каждый код kivy не запускался в новом процессе. Например:

if __name__ == '__main__': # to avoid new window with a new process
    multiprocessing.freeze_support() # support multiprocessing in pyinstaller
    from kivy.lang.builder import Builder
    from kivy.clock import Clock
    from kivy.uix.popup import Popup
    from kivy.uix.textinput import TextInput
    from kivy.uix.scatterlayout import ScatterLayout
    from kivy.graphics.transformation import Matrix
    from kivy.uix.scatter import Scatter
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.properties import BooleanProperty, ListProperty, BoundedNumericProperty, StringProperty, NumericProperty
    from kivy.uix.boxlayout import BoxLayout
    from kivy.app import App
    from kivy.uix.behaviors import ButtonBehavior
    from kivy.uix.image import Image
    from kivy.core.window import Window

Кроме того, все мои классы, использующие kivy, должны были быть помещены в одно и то же предложение if, чтобы избежать ошибок в основной программе.

Мой вывод заключается в том, что некоторое взаимодействие kivy, multiprocessing и pyinstaller делает новое окно всплывающим. Если запустить код напрямую из python, проблема не проявляется. В моем случае я уже использовал одно предложение if для импорта kivy.core.window, и он отлично работал, запуская код непосредственно из python, но не после pyinstaller, даже с использованием freeze_support.

Я надеюсь, что это поможет кому-то.

person Randolfo    schedule 19.10.2018

Дополнительная ошибка для программ в стиле setup.py, которые могут вызвать это:

Если вы используете точки входа для запуска своей программы, вам может понадобиться поместить multiprocessing.freeze_support() внутрь main().

Pyinstaller_setuptools, например, напрямую вызывает main(), пропуская все инструкции в блоке if __name__ == '__main__':.

person houterl    schedule 23.12.2019