V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
cdwyd
V2EX  ›  Python

Python 多线程响应 ctrl+c 优雅退出的方式,代码如下,欢迎交流

  •  
  •   cdwyd · 2016-11-27 21:48:11 +08:00 · 4509 次点击
    这是一个创建于 2914 天前的主题,其中的信息可能已经有所发展或是发生改变。

    对优雅这个词敏感的话,请忽略

    import time
    import random
    from threading import Thread
    
    stop = False
    threads_num = 20
    
    todos = list(range(1000))
    total = len(todos)
    
    def test(name):
        while todos:
            todo = todos.pop()
            # print('{}获取到 todo-{}'.format(name, todo))
            sleep_time = random.randint(1, 5) / 10
            # print('{}休息{}秒'.format(name, sleep_time))
            time.sleep(sleep_time)
            if stop:
                print('{}收到结束信号正在处理'.format(name))
                break
        print('{}结束'.format(name))
    
    
    if __name__ == '__main__':
        start_time = time.time()
        # 启动线程
        threads = []
        for i in range(threads_num):
            t = Thread(target = test, args = ('线程-{}'.format(i),))
            threads.append(t)
            t.start()
        
        # 响应 ctrl+c
        try:
            while todos:
                print('已完成{}中的{},还剩余{}'.format(total, total - len(todos), len(todos)))
                time.sleep(1)
        except KeyboardInterrupt as e:
            print('收到结束信号,正在处理')
            stop = True
    
        # 确认所有子线程结束
        for t in threads:
            t.join()
            
        print('所有子线程已结束')
        print('执行清理工作...')
        print('共计用时{}秒'.format(time.time() - start_time))
    
    7 条回复    2016-11-28 11:01:31 +08:00
    darkbill
        1
    darkbill  
       2016-11-27 23:57:37 +08:00
    曾经试过类似的写法~~~
    ryd994
        2
    ryd994  
       2016-11-28 00:33:20 +08:00 via Android
    子线程里也要响应 keyboard interrupt
    或者使用 signal 模块
    xiamx
        3
    xiamx  
       2016-11-28 00:53:43 +08:00
    很好的 标准做法
    pright
        4
    pright  
       2016-11-28 01:10:55 +08:00
    楼主你可以试试把 time.sleep(sleep_time)里的 sleep_time 改成一个很大的值,再 ctrl+c ,试试是什么结果
    thekoc
        5
    thekoc  
       2016-11-28 09:41:43 +08:00
    我之前也是这么做的,但是就像 @pright 所说, sleep_time 很大的时候直接阻塞在那里了
    cdwyd
        6
    cdwyd  
    OP
       2016-11-28 09:49:52 +08:00 via Android
    @pright
    @thekoc
    子线程运行时间太久会阻塞,响应会有延迟。我主要是写爬虫的时候这么用影响不算大。有其他的方法解决这个问题吗
    thekoc
        7
    thekoc  
       2016-11-28 11:01:31 +08:00   ❤️ 1
    @cdwyd 后来我在 sleep 那里写了一个 while 循环,把时间切分成很小的原子时间,每一次循环都去判断一次,感觉比较丑陋……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1393 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 53ms · UTC 17:36 · PVG 01:36 · LAX 09:36 · JFK 12:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.