Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python2:守护进程线程在键盘中断时未被杀死_Python_Multithreading - Fatal编程技术网

Python2:守护进程线程在键盘中断时未被杀死

Python2:守护进程线程在键盘中断时未被杀死,python,multithreading,Python,Multithreading,我正在编写一个简单的线程应用程序,我将线程设置为守护进程,因为我希望我的程序在键盘中断时退出。这可以很好地使用python3获得预期的结果,但是python2.7似乎不尊重守护进程标志。下面是我的示例代码 if __name__ == '__main__': try: threads = [Thread(target=some_func, args=(arg1,arg2)) for _ in range(10)] for th in threads:

我正在编写一个简单的线程应用程序,我将线程设置为
守护进程
,因为我希望我的程序在
键盘中断时退出。这可以很好地使用
python3
获得预期的结果,但是
python2.7
似乎不尊重
守护进程
标志。下面是我的示例代码

if __name__ == '__main__':
    try:
        threads = [Thread(target=some_func, args=(arg1,arg2)) for _ in range(10)]

        for th in threads:
            th.daemon=True
            th.start()

        for th in threads:
            th.join()
    except KeyboardInterrupt:
        sys.exit('Ctrl-c issued by user .. Exiting')
当我在
python3
上运行此代码,然后按
ctrl-c
一段时间后,我的程序按预期退出,但当我在
python2.7
上运行此代码,然后按
ctrl-c
时,它永远不会退出,我必须从shell中终止进程

我是不是遗漏了什么?我还尝试设置
threading.Event
,然后在
键盘中断发生时清除该事件,但即使这样也不起作用

使用
python3
如果我不
join
my
daemon
线程,那么它们将在my程序完成后立即退出,如果我不将我的线程标记为
daemon
并且不
join
则程序将继续,只要我点击
ctrl-c
它就会退出。但是这些都不适用于
python2.7

编辑#1

我对它做了更多的研究,它看起来像是
python2.7
无法捕捉
KeyboardInterrupt
。这更奇怪,因为
KeyboardInterrupt
工作正常,它是一个非线程程序,但是对于线程
KeyboardInterrupt
不会被捕获,即使线程被标记为
守护进程


所有这些都只发生在
python2.7上,而
python3
工作得很好。

线程的方式。在较旧版本的Python中,join
可以默默地吞下信号,直到
join
完成。这包括SIGINT aka键盘中断

作为一种解决方法,您可以尝试短时间
睡眠
加入
。如果您希望线程自行消亡,请确保清理:

    while threads:
        threads[-1].join(1)  # allow KeyboardInterrup once per second
        if not threads[-1].is_alive():  # reap dead Threads
           threads.pop()

我的第一个想法是使用thread.join,但这似乎会阻止主进程(忽略KeyboardInterrupt),直到线程完成


多线程Python程序通常会忽略键盘中断生成的SIGINT,特别是当获取信号的线程正在等待或休眠时


我使用的是Python2.7,我的程序在使用时忽略SIGTERM信号 线程池执行器

经过一些调试后,我发现我的主线程在thread.join()上被阻塞, 它会保持中断直到呼叫返回


在较旧版本的Python中,
Thread.join
的工作方式可以默默地吞下信号,直到
join
完成。这包括SIGINT aka键盘中断

作为一种解决方法,您可以尝试短时间
睡眠
加入
。如果您希望线程自行消亡,请确保清理:

    while threads:
        threads[-1].join(1)  # allow KeyboardInterrup once per second
        if not threads[-1].is_alive():  # reap dead Threads
           threads.pop()

我的第一个想法是使用thread.join,但这似乎会阻止主进程(忽略KeyboardInterrupt),直到线程完成


多线程Python程序通常会忽略键盘中断生成的SIGINT,特别是当获取信号的线程正在等待或休眠时


我使用的是Python2.7,我的程序在使用时忽略SIGTERM信号 线程池执行器

经过一些调试后,我发现我的主线程在thread.join()上被阻塞, 它会保持中断直到呼叫返回


感谢@mistermiagi的建议,我能够测试本文中提到的一些解决方案

请注意下面的解决方案仅适用于
守护进程
线程,因为如果将
连接
放在主程序上,非守护进程将始终阻止主程序,直到它完成其工作。如果您没有在非守护进程线程上放置一个
join
,那么如果您的main已退出,并且这是预期的行为,那么它们将继续在后台运行

我遇到的问题是专门针对
守护进程
线程的。下面是解决方案

#1:不要在线程上放置联接,因为它会导致线程阻塞主进程。这是因为
守护进程
线程在主程序退出后立即退出,因此当您没有加入
时,您就没有在主程序中等待,这是
时间。睡眠(1)
内部而
只是为了确保
守护进程
线程继续执行,并且只要我点击
ctrl-c
,main将退出,
守护进程
线程也将退出

if __name__ == "__main__":
    try:
        threads = [threading.Thread(name='daemon', target=daemon)
                   for _ in range(8)]

        for th in threads:
            th.daemon = True
            th.start()

    while True:
        time.sleep(1)
    # signal.pause()    # This worked fine for me on Linux, on Windows it doesn't work, not sure about Mac. I am not recommending this because of platform dependency.

    except KeyboardInterrupt:
#2:如果要在线程上放置
连接
,请使用超时,然后在循环检查期间将其保持在
中,直到
线程
处于活动状态。这样做的目的是继续检查
threads
列表中的每个线程,直到它处于活动状态,然后等待1秒执行它。现在由于
条件将为
,直到
线程
完成后实际收割;它将以1秒的时间小块阻塞主程序,一旦您点击
ctrl-c
守护进程线程
将不再处于活动状态,因此主程序退出

if __name__ == "__main__":
    try:
        threads = [threading.Thread(name='daemon', target=daemon)
                   for _ in range(8)]
        for th in threads:
            th.daemon = True
            th.start()

        for th in threads:
            while th.isAlive():
                th.join(1)

    except KeyboardInterrupt:
        print('ctrl-c')

感谢@mistermiagi的建议,我能够测试本文中提到的一些解决方案

请注意下面的解决方案仅适用于
守护进程
线程,因为如果将
连接
放在主程序上,非守护进程将始终阻止主程序,直到它完成其工作。如果您没有在非守护进程线程上放置一个
join
,那么如果您的main已退出,并且这是预期的行为,那么它们将继续在后台运行

我遇到的问题是专门针对
守护进程
线程的。下面是解决方案