带有os.system()调用的Python线程.主线程不在ctrl + c上退出 [英] Python threads with os.system() calls. Main thread doesn't exit on ctrl+c
问题描述
在阅读之前,请不要认为它是重复的.关于multithreading
和keyboard interrupt
的问题很多,但是我没有发现任何考虑使用os.system的东西,它看起来很重要.
Please don't consider it a duplicate before reading, There are a lot of questions about multithreading
and keyboard interrupt
, but i didn't find any considering os.system and it looks like it's important.
我有一个python脚本,该脚本在工作线程中进行一些外部调用.
如果要按ctrl+c
键,我希望它退出,但是看起来主线程忽略了它.
I have a python script which makes some external calls in worker threads.
I want it to exit if I press ctrl+c
But it look like the main thread ignores it.
类似这样的东西:
from threading import Thread
import sys
import os
def run(i):
while True:
os.system("sleep 10")
print i
def main():
threads=[]
try:
for i in range(0, 3):
threads.append(Thread(target=run, args=(i,)))
threads[i].daemon=True
threads[i].start()
for i in range(0, 3):
while True:
threads[i].join(10)
if not threads[i].isAlive():
break
except(KeyboardInterrupt, SystemExit):
sys.exit("Interrupted by ctrl+c\n")
if __name__ == '__main__':
main()
令人惊讶的是,如果我将os.system("sleep 10")
更改为time.sleep(10)
,效果很好.
Surprisingly, it works fine if I change os.system("sleep 10")
to time.sleep(10)
.
推荐答案
我不确定您使用的是哪种操作系统和外壳程序.我用zsh描述了Mac OS X和Linux(bash/sh的行为类似).
I'm not sure what operating system and shell you are using. I describe Mac OS X and Linux with zsh (bash/sh should act similar).
当您按Ctrl + C组合键时,所有在当前终端中前台运行的程序会收到信号SIGINT .在您的情况下,这是您的主要python进程以及os.system产生的所有进程.
When you hit Ctrl+C, all programs running in the foreground in your current terminal receive the signal SIGINT. In your case it's your main python process and all processes spawned by os.system.
由os.system生成的进程然后终止其执行.通常,当python脚本收到SIGINT时,它会引发KeyboardInterrupt异常,但是由于os.system()
,您的主进程会忽略SIGINT. Python os.system()
调用标准C函数 system()
,导致调用过程忽略SIGINT( man Linux /
Processes spawned by os.system then terminate their execution. Usually when python script receives SIGINT, it raises KeyboardInterrupt exception, but your main process ignores SIGINT, because of os.system()
. Python os.system()
calls the Standard C function system()
, that makes calling process ignore SIGINT (man Linux / man Mac OS X).
因此,您的所有python线程都未收到SIGINT,只有子进程才能获得SIGINT.
So neither of your python threads receives SIGINT, it's only children processes who get it.
当您删除os.system()调用时,您的python进程将停止忽略SIGINT,而您得到KeyboardInterrupt
.
When you remove os.system() call, your python process stops ignoring SIGINT, and you get KeyboardInterrupt
.
您可以将os.system("sleep 10")
替换为subprocess.call(["sleep", "10"])
. subprocess.call()
不会使您的进程忽略SIGINT.
You can replace os.system("sleep 10")
with subprocess.call(["sleep", "10"])
. subprocess.call()
doesn't make your process ignore SIGINT.
这篇关于带有os.system()调用的Python线程.主线程不在ctrl + c上退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!