请问 Python 多线程该如何终止程序?

2021-09-28 10:58:08 +08:00
 sudoy

下面是代码结构,我的问题是ctrl+c无法终止程序,请老哥们看下有什么办法,搜了很多比如 signal,try 等方法都不适用

import time
import threading


class Task(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(Task, self).__init__(*args, **kwargs)
        self.daemon = True

    def task1(self):
        while True:
            print("starting task1")
            time.sleep(5)
            print("task1 completed!")

    def task2(self):
        while True:
            print("starting task2")
            time.sleep(15)
            print("task2 completed!")

    def run(self):
        try:
            thread1 = threading.Thread(target=self.task1)
            thread2 = threading.Thread(target=self.task2)
            thread1.start()
            thread2.start()
            thread1.join()
            thread2.join()
        except KeyboardInterrupt:
            print("KeyboardInterrupt has been caught.")
        

if __name__ == "__main__":
    task = Task()
    task.run()

1139 次点击
所在节点    问与答
12 条回复
ipwx
2021-09-28 10:59:51 +08:00
1. time.sleep => condition variable.wait(timeout)
2. self.running = False
3. while not self.running

多线程打断不是正确的写法。正确的写法永远是让线程自己退出。
rationa1cuzz
2021-09-28 11:11:47 +08:00
你 KeyboardInterrupt 把 ctrl+c 操作 try 捕捉,ctrl+c 自然无法终止程序,在外部终止只能通过 kill 或者 signal 9 终止,非则就只能在程序内部做处理,但是你 while true,不会停下来一直跑的。
sudoy
2021-09-28 11:23:54 +08:00
@rationa1cuzz 不用多线程的时候即便是 while true 也可以通过 ctrl+c 终止程序的。我现在添加了一个任务,就得用多线程,然而问题就来了,无法终止任务。
![img]( )
plko345
2021-09-28 11:34:20 +08:00
你别捕获 ctrl c 呀
rationa1cuzz
2021-09-28 13:49:44 +08:00
兄弟,这两行代码就是会捕捉你的 ctrl+c 的操作啊
try:
except KeyboardInterrupt:
你用这代码的目的是啥?
其次你用 join 会一直等待子线程跑完主进程才会关闭,你要是想 ctrl+c 终止,可以不加 join()方法,或者设置线程为 thread1.daemon =True
https://docs.python.org/3/library/threading.html?highlight=threading#module-threading
ipwx
2021-09-28 13:52:55 +08:00
@rationa1cuzz 他设了。

但是后台线程应该让它自己终止,而不应该依赖 daemon = True
sudoy
2021-09-28 14:00:28 +08:00
@rationa1cuzz 我是想 ctrl+c 以后马上结束所有线程。最后换成用 multiprocessing 实现了我的需求。感谢回复!👍
rationa1cuzz
2021-09-28 14:11:48 +08:00
@ipwx 他的 thread1 和 thread2 没有设置吧,只是 task 这个地方是,
另外,我才发现他这个是线程类里又单独起了两个子线程。
不应该依赖外部结束线程这个我也同意
ipwx
2021-09-28 15:02:01 +08:00
time.sleep 用楼主你的代码不容易 interrupt,ctrl + c 还要等。而且 Task 这个对象完全没必要做成 Thread 。给你个例子,Ctrl+C 可以直接立刻打断,并且最后一个 task1 completed 和 task2 completed 是会输出的:

https://gist.github.com/haowen-xu/ddc254bdf251fd2051e39874776e80ba

输出:

starting task1
starting task2
task1 completed!
starting task1
task2 completed!
starting task2
task1 completed!
starting task1
task2 completed!
starting task2
^CKeyboardInterrupt has been caught.
task2 completed!
task1 completed!
sudoy
2021-09-28 15:10:16 +08:00
@ipwx 我这边在 Windows 10 下运行您的代码按 ctrl+c 还是无法打断程序哦
sudoy
2021-09-28 15:11:14 +08:00
@ipwx 问题已经解决了,我把解决方案 append 在这个贴子后面了。感谢回复!
ykk
2021-09-28 16:03:22 +08:00
需要在进程中增加退出条件

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/804833

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX