In PyQt4 I want to execute code with no lock gui. I use QThread and emit signal for gui update. But if i call cython function in QThread.run gui will be locked.
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)
test project is here: https://github.com/ombschervister/test
Due to the GIL (global interpretter lock) only one Python instance can execute at once. How Python chooses to share time between threads depends a bit on the version of Python but it's substantially based on how many Python bytecodes have been executed (see https://docs.python.org/3.0/library/sys.html#sys.setcheckinterval).
I'd guess that since Cython doesn't actually run any Python bytecodes it never releases the GIL, and hence your display will lock. You can release the GIL manually using
with nogil
. In the worst case I'd think that adding:to your loop will work. However, some of your code could definitely be done without the GIL (i.e. not using python features):
You could also use the libc time functions and wrap pretty much the whole function in a
with nogil
block if you wanted, in which case it shouldn't block the GUI at all.