python 优雅的中止任务

例如,我们有一个耗时任务 task

def task():
    while True:
        print(f'task is running!')
        time.sleep(1)

在主线程,可以根据用户输入,随时中止该任务。
一种容易出错的写法是这样:

import threading
import sys

t1 = threading.Thread(target=task)
t1.start()
while True:
    code = input()
    if code == 'stop':
        sys.exit()
    print(code)

当主程序执行到 sys.exit() 时,屏幕上仍然不断打印 task is running!, 只是shell不再接收用户的输入了。这说明,task 线程仍然在运行,阻碍了主程序的退出。

原因是,Python中,非daemon线程并不会随着主线程的退出而退出,daemon 线程则会随着主线程的退出而被杀死。

所以一个简单的改变,让task对应的线程变成deamon线程即可。增加一行代码

t1.daemon = True # 设置线程t1为deamon 线程,则t1会随着 sys.exit() 而死去

不过,这里是强制杀死t1线程,其调用的资源可能不会被正确的释放,因此会导致诡异bug。因此,不推荐这样使用。

更推荐的是使用进程的方式,来管理任务。

import multiprocessing

if __name__ == "__main__":
    process = multiprocessing.Process(target=task)
    process.daemon = True # 这样主进程退出后,task进程也会退出,跟线程类似  a daemonic process is not allowed to create child processes. 
    process.start()

    while True:
        code = input()
        if code == 'stop':
            process.terminate()
            sys.exit()

这是因为,线程之间会共享全局变量,但进程之间是完全隔离的执行环境,所以关闭进程要比关闭线程安全很多。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容