Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有多进程调用时,会重复启动Qt主窗口直到内存耗尽 #21

Closed
rockswang opened this issue Aug 30, 2022 · 2 comments
Closed

Comments

@rockswang
Copy link

入口代码如下,开头会先启动一个后台进程。
python 直接执行正常,通过PyStand.exe 启动,就会不断启动Qt窗口,直到内存耗尽为止。
PyInstaller也有类似问题,按照PyInstaller的方案,加上了freeze_support(),但是问题依旧。
是否需要在PyStand.exe的主程序里添加此调用?

if "__main__" == __name__:
    multiprocessing.freeze_support()
    multiprocessing.Process(target=VideoServer.start_server, daemon=True).start()

    logger.info("启动程序")
    app = QApplication(sys.argv)
    app.setStyleSheet(BASE_STYLE_SHEET)
    win = AppWin(sys.argv)
    win.show()
    sys.exit(app.exec())
myd7349 added a commit to myd7349/PyStand that referenced this issue Aug 31, 2022
@myd7349
Copy link
Contributor

myd7349 commented Aug 31, 2022

可以尝试一下在调用 multiprocessing.freeze_support() 前设置一下 sys.frozen

if not hasattr(sys, 'frozen'):
    sys.frozen = True

multiprocessing.freeze_support()

PyInstaller 的 bootloader 里会帮你设置这个值,因此你只需要调用 freeze_support 就可以了:

https://github.com/pyinstaller/pyinstaller/blob/3ea48fd875e786ecbb3c160209791aa11d55ae99/PyInstaller/loader/pyiboot01_bootstrap.py#L27-L29

https://pyinstaller.org/en/v3.3.1/runtime-information.html

The PyInstaller bootloader adds the name frozen to the sys module.

https://github.com/python/cpython/blob/main/Lib/multiprocessing/context.py

def freeze_support(self):
    '''Check whether this is a fake forked process in a frozen executable.
    If so then run code specified by commandline and exit.
    '''
    if sys.platform == 'win32' and getattr(sys, 'frozen', False):
        from .spawn import freeze_support
        freeze_support()

所以,没设置 sys.frozen 的话,multiprocessing.freeze_support() 就不会起作用。

附一个复现该 Bug 的 case:

PyStand.int:

#  vim: set ts=4 sw=4 tw=0 et ft=python :
import multiprocessing
import sys, os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

import myprocess

if __name__ == '__main__':
    multiprocessing.freeze_support()
    multiprocessing.Process(target=myprocess.say_hello, daemon=True).start()

    app = QApplication([])

    win = QWidget()
    win.setWindowTitle('PyStand')

    layout = QVBoxLayout()

    label = QLabel('Hello, World !!')
    label.setAlignment(Qt.AlignCenter)
    layout.addWidget(label)

    btn = QPushButton(text = 'PUSH ME')
    layout.addWidget(btn)

    win.setLayout(layout)
    win.resize(400, 300)

    btn.clicked.connect(lambda : [
        print('exit'),
        win.close(),
    ])

    win.show()

    app.exec_()

myprocess.py:

def say_hello():
    print('Hello, world!')

myd7349 added a commit to myd7349/PyStand that referenced this issue Aug 31, 2022
@rockswang
Copy link
Author

感谢支持!问题已经修复!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants