从 QThread.run 调用 cython 函数时 pyqt gui 被锁定
pyqt gui locked when calling cython function from QThread.run
在 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)
由于 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。
在 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)
由于 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。