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
Python 为什么signal.SIGTERM没有在我的主线程中正确处理?_Python_Multithreading_Sigterm - Fatal编程技术网

Python 为什么signal.SIGTERM没有在我的主线程中正确处理?

Python 为什么signal.SIGTERM没有在我的主线程中正确处理?,python,multithreading,sigterm,Python,Multithreading,Sigterm,我有连续运行的python代码(收集传感器数据)。它应该在启动时使用启动。然而,我希望能够优雅地终止这个过程,因此我从文章中的建议开始,将我的主循环放在一个单独的线程中。我希望能够在它作为守护进程运行时(启动-停止守护进程将发送终止信号)以及我自己在终端中短暂启动它进行测试时(我按下ctrl-c)优雅地关闭它 但是,如果我终止进程,信号处理程序似乎不会被调用(即使没有使用线程,“done(killed)”也不会出现在我重定向到的文件中)。当我按下ctrl-c键时,采集会继续进行,并在终端(或我重

我有连续运行的python代码(收集传感器数据)。它应该在启动时使用启动。然而,我希望能够优雅地终止这个过程,因此我从文章中的建议开始,将我的主循环放在一个单独的线程中。我希望能够在它作为守护进程运行时(启动-停止守护进程将发送终止信号)以及我自己在终端中短暂启动它进行测试时(我按下
ctrl-c
)优雅地关闭它

但是,如果我终止进程,信号处理程序似乎不会被调用(即使没有使用线程,“
done(killed)
”也不会出现在我重定向到的文件中)。当我按下ctrl-c键时,采集会继续进行,并在终端(或我重定向到的文件)中继续打印数据

以下代码中我做错了什么

from threading import Thread
import time, sys, signal

shutdown_flag = False #used for gracefull shutdown 

def main_loop():
    while not shutdown_flag:
        collect_data() # contains some print "data" statements
        time.sleep(5)
    print "done (killed)"

def sighandler(signum, frame):
    print 'signal handler called with signal: %s ' % signum
    global shutdown_flag
    shutdown_flag = True

def main(argv=None):
    signal.signal(signal.SIGTERM, sighandler) # so we can handle kill gracefully
    signal.signal(signal.SIGINT, sighandler) # so we can handle ctrl-c
    try:
        Thread(target=main_loop, args=()).start()
    except Exception, reason:
        print reason

if __name__ == '__main__':
    sys.exit(main(sys.argv))

您正在使用以下语句终止主线程:

if __name__ == '__main__':
    sys.exit(main(sys.argv))
所以你的信号处理器永远无法运行。信号处理程序是主线程的一部分,而不是您创建的
main\u循环
线程。因此,一旦主线程退出,就不再需要调用信号处理函数了

你需要这样的东西:

def sighandler(signum, frame):
    print 'signal handler called with signal: %s ' % signum
    global shutdown_flag
    shutdown_flag = True
    sys.exit() # make sure you add this so the main thread exits as well.

if __name__ == '__main__':
    main(sys.argv)
    while 1:  # this will force your main thread to live until you terminate it.
       time.sleep(1) 
查看程序中运行了多少线程的简单测试如下:

def main_loop():
    while not shutdown_flag:
        collect_data() # contains some print "data" statements
        time.sleep(5)
        import threading
        print threading.enumerate()
    print "done (killed)"

但是主线怎么可能结束呢?(事实上,发送
kill
停止了向文件输出数据,但是当我执行
ps
时,python进程仍然以相同的方式列出)。另外,我想我在某个地方读到,当使用
Thread(..).start()
时,调用线程会等待生成的线程完成(与
Thread.start\u new\u Thread
库中的
Thread
相反),线程可以标记为“守护线程”。此标志的意义在于,当只剩下守护进程线程时,整个Python程序将退出。初始值从创建线程继承。可以使用setDaemon()方法设置该标志,并使用isDaemon()方法检索该标志。在本例中,主线程不会等待其他线程完成。即使它是守护进程线程,如果您退出主线程,它也将等待其他线程完成,但主线程中的任何代码都不会执行。因此,您将无法调用sig处理程序。你需要让你的主线程保持活跃。嗯,这是一种工作,但不完全。当我从另一个ssh会话执行
kill
时,我确实看到主循环线程被停止(并且“done(killed)”被打印出来。但主线程仍在运行,信号处理程序现在正确打印被调用的信号。无论我是否作为守护进程启动主循环线程,都不会改变这种行为。我看到的行为对我来说似乎是合乎逻辑的,因为如果我们有
而1
循环,主线程就不能结束,不是吗?所以问题仍然存在……哦,是的,我忘记了在
sighandler
函数的末尾需要一个
sys.exit()
。这将迫使主循环退出