下面的代码按照我期望的方式工作,即:
- 有一个从 1 数到 8 的 QThread(“Ernie”),在计数之间休眠 1 秒
- 有一个免费的 UI 小部件(“Bert”)
- 在正常操作下,程序一直运行到线程结束和 UI 关闭为止
- Ctrl-C 键盘中断将在正常完成之前优雅地停止程序。
为此,我必须将 1 秒的 sleep 分成 50 毫秒的 block 来检查标志。
是否有更 Pythonic 的方式让线程休眠一段时间(例如 1 秒)但可被某些标志或信号中断?
try:
for i in xrange(8):
print "i=%d" % i
for _ in xrange(20):
time.sleep(0.05)
if not self.running:
raise GracefulShutdown
except GracefulShutdown:
print "ernie exiting"
我宁愿这样做,并以某种方式在线程中导致 GracefulShutdown 异常:
try:
for i in xrange(8):
print "i=%d" % i
time.sleep(1)
# somehow allow another thread to raise GracefulShutdown
# during the sleep() call
except GracefulShutdown:
print "ernie exiting"
完整程序;
from PySide import QtCore, QtGui
from PySide.QtGui import QApplication
import sys
import signal
import time
class GracefulShutdown(Exception):
pass
class Ernie(QtCore.QThread):
def __init__(self):
super(Ernie, self).__init__()
self.running = True
def run(self):
try:
for i in xrange(8):
print "i=%d" % i
for _ in xrange(20):
time.sleep(0.05)
if not self.running:
raise GracefulShutdown
except GracefulShutdown:
print "ernie exiting"
def shutdown(self):
print "ernie received request to shutdown"
self.running = False
class Bert(object):
def __init__(self, argv):
self.app = QApplication(argv)
self.app.quitOnLastWindowClosed = False
def show(self):
widg = QtGui.QWidget()
widg.resize(250, 150)
widg.setWindowTitle('Simple')
widg.show()
self.widg = widg
return widg
def shutdown(self):
print "bert exiting"
self.widg.close()
def start(self):
# return control to the Python interpreter briefly every 100 msec
timer = QtCore.QTimer()
timer.start(100)
timer.timeout.connect(lambda: None)
return self.app.exec_()
def handleInterrupts(*actors):
def handler(sig, frame):
print "caught interrupt"
for actor in actors:
actor.shutdown()
signal.signal(signal.SIGINT, handler)
bert = Bert(sys.argv)
gratuitousWidget = bert.show()
ernie = Ernie()
ernie.start()
handleInterrupts(bert, ernie)
retval = bert.start()
print "bert finished"
while not ernie.wait(100):
# return control to the Python interpreter briefly every 100 msec
pass
print "ernie finished"
sys.exit(retval)
最佳答案
我不确定它有多 Pythonic,但它确实有效。只需使用队列并使用超时阻塞获取。请参见下面的示例:
import threading
import Queue
import time
q = Queue.Queue()
def workit():
for i in range(10):
try:
q.get(timeout=1)
print '%s: Was interrupted' % time.time()
break
except Queue.Empty:
print '%s: One second passed' % time.time()
th = threading.Thread(target=workit)
th.start()
time.sleep(3.2)
q.put(None)
关于python - 是否有优雅或 Pythonic 的方式来中断线程中的 time.sleep() 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24617131/