pyqt gui 在从 QThread.run 调用 cython 函数时锁定



在 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。

相关内容

  • 没有找到相关文章

最新更新