V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
sudoy
V2EX  ›  问与答

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

  •  
  •   sudoy · 2021-09-28 10:58:08 +08:00 · 1140 次点击
    这是一个创建于 1156 天前的主题,其中的信息可能已经有所发展或是发生改变。

    下面是代码结构,我的问题是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()
    
    
    第 1 条附言  ·  2021-09-28 13:56:52 +08:00
    感谢大家的回复!以下是我整理的解决方案,希望对其他有需要的 V 友有帮助。

    像我这种情况最好是用 `multiprocessing` 而不是 `threading`。因为用`threading`按`ctrl+c`以后需要等最后一个循环执行结束才可以退出。

    参考来源:
    https://stackoverflow.com/questions/11436502/closing-all-threads-with-a-keyboard-interrupthttps://www.geeksforgeeks.org/multiprocessing-python-set-1/#highlighter_806430

    1. 用 `multiprocessing`
    ( )


    2. 如果非要用 `threading`, 如下:
    ( )
    12 条回复    2021-09-28 16:03:22 +08:00
    ipwx
        1
    ipwx  
       2021-09-28 10:59:51 +08:00   ❤️ 1
    1. time.sleep => condition variable.wait(timeout)
    2. self.running = False
    3. while not self.running

    多线程打断不是正确的写法。正确的写法永远是让线程自己退出。
    rationa1cuzz
        2
    rationa1cuzz  
       2021-09-28 11:11:47 +08:00
    你 KeyboardInterrupt 把 ctrl+c 操作 try 捕捉,ctrl+c 自然无法终止程序,在外部终止只能通过 kill 或者 signal 9 终止,非则就只能在程序内部做处理,但是你 while true,不会停下来一直跑的。
    sudoy
        3
    sudoy  
    OP
       2021-09-28 11:23:54 +08:00
    @rationa1cuzz 不用多线程的时候即便是 while true 也可以通过 ctrl+c 终止程序的。我现在添加了一个任务,就得用多线程,然而问题就来了,无法终止任务。
    ![img]( )
    plko345
        4
    plko345  
       2021-09-28 11:34:20 +08:00 via Android
    你别捕获 ctrl c 呀
    rationa1cuzz
        5
    rationa1cuzz  
       2021-09-28 13:49:44 +08:00   ❤️ 1
    兄弟,这两行代码就是会捕捉你的 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
        6
    ipwx  
       2021-09-28 13:52:55 +08:00   ❤️ 1
    @rationa1cuzz 他设了。

    但是后台线程应该让它自己终止,而不应该依赖 daemon = True
    sudoy
        7
    sudoy  
    OP
       2021-09-28 14:00:28 +08:00
    @rationa1cuzz 我是想 ctrl+c 以后马上结束所有线程。最后换成用 multiprocessing 实现了我的需求。感谢回复!👍
    rationa1cuzz
        8
    rationa1cuzz  
       2021-09-28 14:11:48 +08:00
    @ipwx 他的 thread1 和 thread2 没有设置吧,只是 task 这个地方是,
    另外,我才发现他这个是线程类里又单独起了两个子线程。
    不应该依赖外部结束线程这个我也同意
    ipwx
        9
    ipwx  
       2021-09-28 15:02:01 +08:00   ❤️ 1
    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
        10
    sudoy  
    OP
       2021-09-28 15:10:16 +08:00
    @ipwx 我这边在 Windows 10 下运行您的代码按 ctrl+c 还是无法打断程序哦
    sudoy
        11
    sudoy  
    OP
       2021-09-28 15:11:14 +08:00
    @ipwx 问题已经解决了,我把解决方案 append 在这个贴子后面了。感谢回复!
    ykk
        12
    ykk  
       2021-09-28 16:03:22 +08:00
    需要在进程中增加退出条件
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5508 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 09:02 · PVG 17:02 · LAX 01:02 · JFK 04:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.