Pyinstaller在使用线程时存在问题。

9
运行一个包含使用Qthread运行可执行文件(longTask)指令的批处理文件,但当我使用以下命令创建一个可执行文件时,它无法按预期工作。 我给了'--windowed'以不为标准I / O提供控制台窗口。 pyinstaller --onefile --windowed main.py 但有趣的是,当我删除--windowed参数时,它按预期工作。
pyinstaller --onefile main.py

这里是代码:

from PyQt4.Qt import *
import subprocess


def callSubprocess():
    page = QWizardPage()
    page.setTitle("Run myLongTask")

    runButton = QPushButton("Run")
    progressBar = QProgressBar()
    procLabel = QLabel()
    procLabel1 = QLabel()
    progressBar.setRange(0, 1)

    layout = QGridLayout()
    layout.addWidget(runButton, 0, 0)
    layout.addWidget(progressBar, 0, 1)
    layout.addWidget(procLabel)
    layout.addWidget(procLabel1)

    # Calls thread class
    myLongTask = TaskThread()
    runButton.clicked.connect(lambda: OnStart(myLongTask, progressBar, procLabel1))
    myLongTask.taskFinished.connect(lambda: onFinished(progressBar, procLabel))
    page.setLayout(layout)
    return page


def OnStart(myLongTask, progressBar, procLabel1):
    progressBar.setRange(0, 0)
    myLongTask.start()
    # I am waiting until my subprocess completes
    while not myLongTask.isFinished():
        QCoreApplication.processEvents()
    procLabel1.setText("Hello This is main")


def onFinished(progressBar, procLabel):
        # Stop the pulsation
        progressBar.setRange(0, 1)
        procLabel.setText("longTask finished")


class TaskThread(QThread):
    taskFinished = pyqtSignal()
    def __init__(self):
        QThread.__init__(self)

    def run(self):
        proc = subprocess.Popen(r'C:\Users\Desktop\runInf.bat', bufsize=0, shell=True,  stdout=subprocess.PIPE)
        proc.wait()
        self.taskFinished.emit()

    def __del__(self):
        self.wait()


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    wizard = QWizard()
    wizard.addPage(callSubprocess())
    wizard.setWindowTitle("Example Application")
    wizard.show()

sys.exit(wizard.exec_())

当在Pycharm中执行以上代码时,它按预期工作。但是,在使用PyInstaller构建时,主线程不会等待子进程完成。
有什么办法可以创建一个可执行文件,使线程按预期工作。 提前感谢您的帮助。

你有什么证据表明qthreads无法工作的问题?我认为更可能的是你的程序找不到runInf.bat,因此线程会在你预期之前结束(当使用pyinstaller时)。 - three_pineapples
@three_pineapples 謝謝您的回復。我給了絕對路徑,但它仍然不起作用。 - Nagamani
我建议您进行更多的调试,以查看到底是哪里出了问题,并且出现了什么错误信息。如果没有更多的信息,我不确定我能提供帮助。 - three_pineapples
@three_pineapples 谢谢。我真的尝试了很多次,但是一直找不到解决方案。如果你能运行上面的代码,你就能看到问题了。 - Nagamani
2个回答

5

我已经解决了这个问题。我的发现如下:

罪魁祸首是subprocess。所以我用文件处理代替了subprocess(比方说打开一个文件10000次并写入一些内容),它正常工作,这意味着主线程等待子进程完成。

因此,Pyinstaller与线程一起使用没有问题

我添加了几个参数。

proc = subprocess.Popen(os.getcwd() + r'\runInf.bat',
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            stdin=subprocess.PIPE,
                            cwd=os.getcwd(),
                            env=os.environ)
proc.stdin.close()

这个更改使子进程运行,并且主线程也会等待其完成。

2
看起来这是一个已知的问题,与pyinstaller,子进程和--noconsole标志(它与--windowed标志相同)有关。很高兴您设法找到了解决方法! - three_pineapples

1

我曾经遇到过类似的问题,后来在.spec文件中使用了"console=True"语句解决了这个问题。如果没有控制台,线程将不会被执行。


1
似乎更像是一条注释 - StupidWolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接