V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
liangmishi
V2EX  ›  程序员

python 多线程 Ctrl + c 强行停止后会锁死吗?

  •  
  •   liangmishi · 2016-08-14 20:33:02 +08:00 · 4961 次点击
    这是一个创建于 3014 天前的主题,其中的信息可能已经有所发展或是发生改变。
    写了个多线程,由于需要再调试, Ctrl + C 强行停止之后在运行
    本来是会 print 很多东西的,但是无任何回显 也没有结束,感觉就是一直卡着
    各位哥哥姐姐们,有遇到过这种情况吗~
    第 1 条附言  ·  2016-08-14 21:29:50 +08:00
    pool.apply_async(mytest, args=(test))
    改为
    pool.apply_async(mytest, args=(test)) .get(30)可解

    30 表示的是超时时间
    15 条回复    2016-08-15 18:50:46 +08:00
    liangmishi
        1
    liangmishi  
    OP
       2016-08-14 20:35:39 +08:00
    代码是这样的:
    from multiprocessing.dummy import Pool
    pool = Pool(10)
    for i in range(10):
    pool.apply_async(mytest, args=(test))
    pool.close()
    pool.join()
    fiht
        2
    fiht  
       2016-08-14 20:52:52 +08:00
    因为 线程调度,主线程被挂起了,无法接收系统传来的 KeyboardInterrupt 。
    ChopinWong
        3
    ChopinWong  
       2016-08-14 21:11:51 +08:00
    killall python
    liangmishi
        4
    liangmishi  
    OP
       2016-08-14 21:28:40 +08:00
    @fiht 找了相关的资料,确实如此。 pool.apply_async(mytest, args=(test)) 加一个 get()来接收超时时间可解

    @ChopinWong 谢谢~ 我刚刚开始也是没想到用 kill 直接重启了。。
    cloverstd
        5
    cloverstd  
       2016-08-14 21:59:22 +08:00   ❤️ 1
    我最近也在做多线程(进程)相关的程序,我的解决办法是继承 threading.Thread 或者 multiprocessing.Process
    然后在 run 里面通过 self._running 来判断是否继续运行,然后 self._running 的值由主线程传递进来
    所以我在主进程里捕捉 KeyboardInterrupt ,然后依次将子线程 stop 掉
    skydiver
        6
    skydiver  
       2016-08-14 22:19:46 +08:00   ❤️ 1
    通用做法是主线程捕获信号并 set 个 flag ,然后子线程检查这个 flag 并自己退出循环。

    多进程的话,应该是主进程捕获信号然后给子进程发信号吧
    wevsty
        7
    wevsty  
       2016-08-15 00:02:31 +08:00
    我用 multiprocessing pool 写的多进程代码会莫名其妙的出现 error 或者崩溃,还在和社区的人反馈。汗一个。。。
    suueyoung
        8
    suueyoung  
       2016-08-15 09:26:55 +08:00
    @wevsty
    那应该是你的 func 有问题没跑了.
    wevsty
        9
    wevsty  
       2016-08-15 09:40:17 +08:00
    @suueyoung 我正在头疼是什么问题, error 的部分是标准库里面的实现,并非直接是我代码中的问题。但是有几点,首先 python.exe 有 crash 的现象,这个 crash 的锅我不背,无论什么时候解释器 crash 都是有问题的。
    然后 error 报错的位置在
    lib\multiprocessing\connection.py", line 280, in _send_bytes
    ov, err = _winapi.WriteFile(self._handle, buf, overlapped=True)
    TypeError: WriteFile() argument 1 must be int, not None
    self._handle 这东西根本不是我传入的参数, lib 里面自己处理的,我实在不明白这代码哪里有问题
    G_Process_Lock = multiprocessing.Manager().Lock()
    然后再其他进程里面
    with G_Process_Lock:
    pass
    然而这代码就是有概率在 with 退出的时候出现上面的 error 。如果有人能告诉我是哪里出现了问题,我非常感谢。
    xiaolee59
        10
    xiaolee59  
       2016-08-15 11:12:31 +08:00   ❤️ 1
    https://cyrusin.github.io/2016/05/25/python20160525/
    “从 Ctrl-C 看 Python 多线程的信号处理”
    不知道你的问题是不是踩到了 Python 多线程问题的一个坑, ctrl-c 问题涉及到 Python 的多线程的信号处理的问题,可以看我的文章,理解下。
    hitmanx
        11
    hitmanx  
       2016-08-15 13:00:16 +08:00   ❤️ 1
    python 的多线程用的不多不太了解:(,不过 general 的多线程和信号的问题可以看看 APUE 里 Thread Control 那章,专门有一节是讲多线程的情况下的 signal 的处理的,叫 threads and signals.虽然是 POSIX 的,但是很多思路是一样的。
    hitmanx
        12
    hitmanx  
       2016-08-15 13:04:58 +08:00
    @xiaolee59 文章写得很清晰,赞
    liangmishi
        13
    liangmishi  
    OP
       2016-08-15 15:07:39 +08:00
    @cloverstd 方法不错,不过好像也就这个方法

    @skydiver 设置信号量,这是不是只能用在有循环的线程里

    @xiaolee59 感谢您的文章,受益匪浅

    @hitmanx 研究了一番,思路确实都差不多,只要能让它懂得停下来就好
    wwqgtxx
        14
    wwqgtxx  
       2016-08-15 15:19:04 +08:00
    @xiaolee59 可以考虑在 signal_handler(signum, frame)中直接执行 os._exit(0),这样就不用考虑线程会不会退出了
    EchoUtopia
        15
    EchoUtopia  
       2016-08-15 18:50:46 +08:00   ❤️ 1
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5595 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 06:41 · PVG 14:41 · LAX 22:41 · JFK 01:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.