当 python 代码被 cx_Freeze 冻结时,QThread 在解码 UTF-16 时阻塞?
QThread blocks in decoding UTF-16 when python code is freezed by cx_Freeze?
其实这个问题是一个庞大系统的严重bug,我们把问题简化成下面的代码片段。我们想弄清楚为什么 python 代码和 exe 文件中的线程行为不同。
该代码包含两个线程,我们希望这两个线程可以同时 运行 并在 Windows 7(64 位)和 python 2.7 中终止。
当我直接使用 CPython 时,代码 运行s 是正确的,比如说,在控制台中使用 "python tThread.py"。两个线程都 运行 并正常完成。
但是,当代码用cx_Freeze 5.0.1冻结成exe执行时,子线程阻塞在uu = u16.decode("utf-16") ,而主线程进入死循环。
下面是tThread.py:
# -*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import time
from PySide import QtGui, QtCore
from PySide.QtCore import *
from PySide.QtGui import *
class Worker(QObject):
done = QtCore.Signal()
def longRun(self):
count = 1
while count < 20:
print "Worker Thread", count
u16 = u"ABCD".encode("utf-16")
uu = u16.decode("utf-16") # Block here <---
count += 1
self.done.emit()
def mainThread():
app = QApplication([])
objThread = QThread()
obj = Worker()
obj.moveToThread(objThread)
obj.done.connect(objThread.quit)
objThread.started.connect(obj.longRun)
objThread.start()
i = 1
while not objThread.isFinished():
QCoreApplication.processEvents()
print "Main Thread", i
time.sleep(0.1)
i+=1
print "Main Thread Over"
mainThread()
sys.exit()
下面是 setup.py 文件 cx_Freeze :
(控制台命令是“python setup.py build_exe -b build”)
from cx_Freeze import setup, Executable
import platform
build_exe_options = {
"packages": [ "PySide"],
"include_msvcr": True
};
exe = Executable(u".\tThread.py", base=None, targetName="tThread.exe" )
setup( name = "tThread",
version = "0.1",
description = u"tThread",
options = {"build_exe": build_exe_options},
executables = [exe])
我们怀疑 cx_Freeze 中存在错误,导致原始代码和 exe 之间的行为不同。
请帮助我们找到使线程通过解码代码的解决方案,谢谢。
经过几天的艰苦调试,我们在$Python27$\Lib\encodings\__init__.py
中找到这一行的线程块
mod = __import__('encodings.' + modname, fromlist=_import_tail,level=0)
cx_Freeze 在多线程中存在 运行time 模块导入错误。
最后,我们使用hack-code绕过阻塞代码,比如手动导入线程代码之外的模块。但是,我们认为这不是一个优雅的解决方案,因为仍然存在将来可能会发生的隐藏导入错误。
希望cx_Freeze作者能修复bug,完美解决我们的问题。
cx_Freeze的作者已经解决bug并更新到5.0.2.
相关问题是Here
其实这个问题是一个庞大系统的严重bug,我们把问题简化成下面的代码片段。我们想弄清楚为什么 python 代码和 exe 文件中的线程行为不同。
该代码包含两个线程,我们希望这两个线程可以同时 运行 并在 Windows 7(64 位)和 python 2.7 中终止。
当我直接使用 CPython 时,代码 运行s 是正确的,比如说,在控制台中使用 "python tThread.py"。两个线程都 运行 并正常完成。
但是,当代码用cx_Freeze 5.0.1冻结成exe执行时,子线程阻塞在uu = u16.decode("utf-16") ,而主线程进入死循环。
下面是tThread.py:
# -*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import time
from PySide import QtGui, QtCore
from PySide.QtCore import *
from PySide.QtGui import *
class Worker(QObject):
done = QtCore.Signal()
def longRun(self):
count = 1
while count < 20:
print "Worker Thread", count
u16 = u"ABCD".encode("utf-16")
uu = u16.decode("utf-16") # Block here <---
count += 1
self.done.emit()
def mainThread():
app = QApplication([])
objThread = QThread()
obj = Worker()
obj.moveToThread(objThread)
obj.done.connect(objThread.quit)
objThread.started.connect(obj.longRun)
objThread.start()
i = 1
while not objThread.isFinished():
QCoreApplication.processEvents()
print "Main Thread", i
time.sleep(0.1)
i+=1
print "Main Thread Over"
mainThread()
sys.exit()
下面是 setup.py 文件 cx_Freeze :
(控制台命令是“python setup.py build_exe -b build”)
from cx_Freeze import setup, Executable
import platform
build_exe_options = {
"packages": [ "PySide"],
"include_msvcr": True
};
exe = Executable(u".\tThread.py", base=None, targetName="tThread.exe" )
setup( name = "tThread",
version = "0.1",
description = u"tThread",
options = {"build_exe": build_exe_options},
executables = [exe])
我们怀疑 cx_Freeze 中存在错误,导致原始代码和 exe 之间的行为不同。 请帮助我们找到使线程通过解码代码的解决方案,谢谢。
经过几天的艰苦调试,我们在$Python27$\Lib\encodings\__init__.py
中找到这一行的线程块 mod = __import__('encodings.' + modname, fromlist=_import_tail,level=0)
cx_Freeze 在多线程中存在 运行time 模块导入错误。
最后,我们使用hack-code绕过阻塞代码,比如手动导入线程代码之外的模块。但是,我们认为这不是一个优雅的解决方案,因为仍然存在将来可能会发生的隐藏导入错误。 希望cx_Freeze作者能修复bug,完美解决我们的问题。
cx_Freeze的作者已经解决bug并更新到5.0.2.
相关问题是Here