【问题标题】:Stop threads gracefully优雅地停止线程
【发布时间】:2019-11-10 16:01:46
【问题描述】:

我即将完成我的程序,我想在发布我的第一个版本之前修复这个错误。

这就是我所说的错误:

Exception ignored in: <module 'threading' from '/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py'>
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1281, in _shutdown
    t.join()
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1032, in join
    self._wait_for_tstate_lock()
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1048, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

我这样开始线程:

def init(self):

    new_post_stream_thread = threading.Thread(target=self.new_post_stream)
    process_posts = threading.Thread(target=self.process_posts)
    print('\nStarting threads...')
    print('- - - - - - - - - -\n')
    new_post_stream_thread.start()
    process_posts.start()

基本上就是这样。我将如何捕捉到这个异常?我尝试了尝试,但它没有捕获任何东西。

这是 MCVE:

import threading
import time

class MCVE:

    def __init__(self):

        self.list_1 = []

        self.init()

    def thread_1(self):

        while True:
            self.list_1.append('whatever')
            time.sleep(5)

    def thread_2(self):

        while True:
            for id, entry in enumerate(self.list_1):
                print('ID {} | entry: {}'.format(id, entry))
            time.sleep(10)

    def init(self):
        thread_1 = threading.Thread(target=self.thread_1)
        thread_2 = threading.Thread(target=self.thread_2)
        print('\nStarting threads...')
        print('- - - - - - - - - -\n')
        thread_1.start()
        thread_2.start()


def main():

    example = MCVE()

if __name__ == "__main__":
    main()

【问题讨论】:

  • new_post_streamprocess_posts 是什么?你的意思是使用名为init 的方法而不是魔术构造函数__init__
  • 第一个线程从源中流式传输帖子,第二个线程在它们可用时立即处理它们。是的,init 是从 __init__ 调用的,我想让代码更简洁一些。
  • 实际上这可能会有所帮助:stackoverflow.com/questions/3788208/…

标签: python multithreading


【解决方案1】:

您没有提供可重现的示例,但这成功地停止了程序而不会引发未捕获的异常:

def foo(n):
    import time
    try:
        for i in range(n):
            time.sleep(i)
    except KeyboardInterrupt:
        print("Clean exit....")
        return

【讨论】:

  • 它只是一个函数。你可以打电话给foo(5),在它运行的时候,按下Control+C,你会看到打印出来的信息
  • 好的。这对我不起作用。我不确定我应该在哪里使用这个except,才能成功捕获这个错误。
  • 您可以首先使用try/except 包装每个级别的所有可能调用,看看它是否有效。如果是这样,只需删除呼叫,直到找到正在工作的呼叫。如果它不起作用,则可能需要一些特殊的线程魔法。
  • 你能解释一下这个线程魔法吗?该程序非常大,将每个调用都包装在 try/except 中有点乏味。
  • 找到了解决办法。 thread.daemon = True + except KeyboardInterrupt in main() 可以解决问题。
【解决方案2】:

这可能有点晚了,在线程模块中尝试“Event()”方法,然后使用信号模块及其方法来捕获信号。我将在下面留下一个链接,Miguel Grinberg 对此进行了简单而清晰的解释。

链接:https://blog.miguelgrinberg.com/post/how-to-kill-a-python-thread

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
猜你喜欢
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多