在 PyQt4 中,我想在没有锁定 gui 的情况下执行代码。我使用 QThread 并发出信号进行 gui 更新。但是如果我在QThread.run gui中调用cython函数将被锁定。
class Runner(QtCore.QThread):
iter = QtCore.pyqtSignal(int)
def __init__(self):
QtCore.QThread.__init__(self)
def do_something(self):
beg = time.time()
s = 0.0
while time.time() - beg < 1:
s += math.sqrt(1000)
def run(self):
for it in xrange(10):
# no lock gui
#self.do_something()
# lock gui
cython_unit.do_something()
self.iter.emit(it + 1)
cython_unit.pyx:
import math
import time
def do_something():
beg = time.time()
s = 0.0
while time.time() - beg < 1:
s += math.sqrt(1000)
测试项目在这里: https://github.com/ombschervister/test
由于 GIL(全局解释器锁),一次只能执行一个 Python 实例。Python 选择如何在线程之间共享时间有点取决于 Python 的版本,但它在很大程度上取决于已执行的 Python 字节码数量(参见 https://docs.python.org/3.0/library/sys.html#sys.setcheckinterval)。
我猜由于Cython实际上并没有运行任何Python字节码,它永远不会释放GIL,因此您的显示器将锁定。您可以使用 with nogil
手动释放 GIL。在最坏的情况下,我认为添加:
with nogil:
pass
到你的循环将工作。但是,您的某些代码绝对可以在没有 GIL 的情况下完成(即不使用 python 功能):
from libc.math cimport sqrt # don't use Python math module
import time
def do_something():
beg = time.time()
cdef double s = 0 # typed as a double, not a python object
while time.time() - beg < 1:
with nogil:
s += sqrt(1000) # now using C sqrt, not the python one
如果需要,您还可以使用 libc time 函数并将几乎整个函数包装在一个with nogil
块中,在这种情况下,它根本不应该阻止 GUI。