cx_Freeze 使用 PyQt5 和线程
cx_Freeze with PyQt5 and Threading
如果我 运行 下面的 thread_test.py 代码,我在线程中的函数 运行 没问题。但是,如果我用 cx_Freeze 编译它,那么它会在调用 glob 时挂断。它没有给出错误并且 gui 保持响应,但线程似乎挂起(什么都不做)。除了 glob,我还测试了其他几个函数,所以 glob 本身 不是 问题。我尝试从多处理中添加 freeze_support,即使我没有使用多处理,但这没有帮助。关于可能导致这种情况的原因有什么想法吗?这可能与使用 Anaconda 而不是 vanilla 有关吗 python?
我意识到像这样使用日志可能不是线程安全的,但对于这个演示来说没问题。
作为参考,我使用的是:
- Windows 7 企业版,Service Pack 1
- 蟒蛇 4.2.0(Python2.7.12)
- cx_Freeze 5.0
- PyQt5 5.6.0
thread_test.py:
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import sys
import time
import glob
import logging
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.addHandler(logging.StreamHandler())
class worker_object(QObject):
finished = pyqtSignal()
def __init__(self):
super(self.__class__, self).__init__()
log.info('2. Worker Object Initialized')
@pyqtSlot()
def run_thread(self):
log.info('5. Worker 1/5')
time.sleep(0.5)
log.info(' Worker 2/5')
glob.glob('*.jpg')
log.info(' Worker 3/5')
time.sleep(0.5)
log.info(' Worker 4/5')
self.finished.emit()
log.info(' Worker 5/5')
class test_window(QMainWindow):
def __init__(self):
super(self.__class__, self).__init__()
log.info('1. Window Initialization (Started)')
self.centralwidget = QtWidgets.QWidget(self)
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setText('Start!')
self.verticalLayout.addWidget(self.pushButton)
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setRange(0,1)
self.verticalLayout.addWidget(self.progressBar)
self.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(self)
self.setStatusBar(self.statusbar)
self.pushButton.clicked.connect(self.execute)
# Setup threading
self.thread = QThread()
self.worker_object = worker_object()
self.worker_object.moveToThread(self.thread)
self.worker_object.finished.connect(self.onFinished)
self.thread.started.connect(self.worker_object.run_thread)
log.info('3. Window Initialization (Finished)')
def onFinished(self):
self.thread.quit()
self.statusbar.showMessage('Finished!')
self.setEnabled(True)
self.progressBar.setRange(0,1)
log.info('6. Thread Finished')
def execute(self):
self.statusbar.showMessage('Working')
self.setEnabled(False)
self.progressBar.setRange(0,0)
log.info('4. Thread Starting')
self.thread.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
form = test_window()
form.show()
app.exec_()
setup.py:
from cx_Freeze import setup, Executable
buildOptions = dict(packages = [], excludes = [], includes = [], include_files = [])
executables = [Executable('thread_test.py', base=None)]
setup(name='thread_test',
version = '1.0',
description = 'Threading Test',
options = dict(build_exe = buildOptions),
executables = executables)
为了它的价值,我刚刚安装了 Anaconda3(Anaconda 4.2.0 和 Python 3.5.2)并安装了 cx_Freeze。使用它,一切正常。所以也许这是 python 2.7 上的 cx_Freeze 中的错误,我不确定。
如果我 运行 下面的 thread_test.py 代码,我在线程中的函数 运行 没问题。但是,如果我用 cx_Freeze 编译它,那么它会在调用 glob 时挂断。它没有给出错误并且 gui 保持响应,但线程似乎挂起(什么都不做)。除了 glob,我还测试了其他几个函数,所以 glob 本身 不是 问题。我尝试从多处理中添加 freeze_support,即使我没有使用多处理,但这没有帮助。关于可能导致这种情况的原因有什么想法吗?这可能与使用 Anaconda 而不是 vanilla 有关吗 python?
我意识到像这样使用日志可能不是线程安全的,但对于这个演示来说没问题。
作为参考,我使用的是:
- Windows 7 企业版,Service Pack 1
- 蟒蛇 4.2.0(Python2.7.12)
- cx_Freeze 5.0
- PyQt5 5.6.0
thread_test.py:
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import sys
import time
import glob
import logging
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.addHandler(logging.StreamHandler())
class worker_object(QObject):
finished = pyqtSignal()
def __init__(self):
super(self.__class__, self).__init__()
log.info('2. Worker Object Initialized')
@pyqtSlot()
def run_thread(self):
log.info('5. Worker 1/5')
time.sleep(0.5)
log.info(' Worker 2/5')
glob.glob('*.jpg')
log.info(' Worker 3/5')
time.sleep(0.5)
log.info(' Worker 4/5')
self.finished.emit()
log.info(' Worker 5/5')
class test_window(QMainWindow):
def __init__(self):
super(self.__class__, self).__init__()
log.info('1. Window Initialization (Started)')
self.centralwidget = QtWidgets.QWidget(self)
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setText('Start!')
self.verticalLayout.addWidget(self.pushButton)
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setRange(0,1)
self.verticalLayout.addWidget(self.progressBar)
self.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(self)
self.setStatusBar(self.statusbar)
self.pushButton.clicked.connect(self.execute)
# Setup threading
self.thread = QThread()
self.worker_object = worker_object()
self.worker_object.moveToThread(self.thread)
self.worker_object.finished.connect(self.onFinished)
self.thread.started.connect(self.worker_object.run_thread)
log.info('3. Window Initialization (Finished)')
def onFinished(self):
self.thread.quit()
self.statusbar.showMessage('Finished!')
self.setEnabled(True)
self.progressBar.setRange(0,1)
log.info('6. Thread Finished')
def execute(self):
self.statusbar.showMessage('Working')
self.setEnabled(False)
self.progressBar.setRange(0,0)
log.info('4. Thread Starting')
self.thread.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
form = test_window()
form.show()
app.exec_()
setup.py:
from cx_Freeze import setup, Executable
buildOptions = dict(packages = [], excludes = [], includes = [], include_files = [])
executables = [Executable('thread_test.py', base=None)]
setup(name='thread_test',
version = '1.0',
description = 'Threading Test',
options = dict(build_exe = buildOptions),
executables = executables)
为了它的价值,我刚刚安装了 Anaconda3(Anaconda 4.2.0 和 Python 3.5.2)并安装了 cx_Freeze。使用它,一切正常。所以也许这是 python 2.7 上的 cx_Freeze 中的错误,我不确定。