【问题标题】:pyqt gui locked when calling cython function from QThread.run从 QThread.run 调用 cython 函数时 pyqt gui 被锁定
【发布时间】:2015-09-02 15:50:03
【问题描述】:

在 PyQt4 中,我想执行没有锁 gui 的代码。 我使用 QThread 并发出信号进行 gui 更新。 但是如果我在 QThread.run 中调用 cython 函数,gui 将被锁定。

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

【问题讨论】:

    标签: python user-interface pyqt cython qthread


    【解决方案1】:

    由于 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 时间函数并将几乎整个函数包装在 with nogil 块中,在这种情况下,它根本不应该阻塞 GUI。

    【讨论】:

      猜你喜欢
      • 2012-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-26
      • 1970-01-01
      • 2018-08-31
      相关资源
      最近更新 更多