python - 是否有优雅或 Pythonic 的方式来中断线程中的 time.sleep() 调用?

标签 python multithreading

下面的代码按照我期望的方式工作,即:

  • 有一个从 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/

相关文章:

python - 使用 sklearns 的 LabelEncoder() 时如何检查分配给哪个标签的值?

python - Pandas 按名称索引和访问列

python - 如何从脚本向应用引擎发出经过身份验证的请求?

c# - 子线程结束后如何在主线程中运行一个方法?

Java 多线程 - 识别代码中的错误

c# - 如何使用多线程 C# 应用程序在 Redis 中插入数百万个键/值

python - python 函数中默认参数的值

python - 如何使用 lxml 在属性值中设置 namespace 前缀?

java - 多线程不起作用

java - 如何在请求处理线程和 SocketChannel 选择器线程之间建立 happens-before 关系?