Sha*_*dor 5 python multithreading os.system keyboardinterrupt
请不要在阅读之前认为它是重复的,有很多关于multithreading和的问题keyboard interrupt,但我没有发现任何考虑os.system,它看起来很重要.
我有一个python脚本,它在工作线程中进行一些外部调用.我希望它退出,如果我按,ctrl+c但看起来主线程忽略它.
像这样的东西:
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()
Run Code Online (Sandbox Code Playgroud)
出人意料的是,如果我改变它工作正常os.system("sleep 10")来time.sleep(10).
我不确定您使用的是什么操作系统和外壳。我用 zsh 描述了 Mac OS X 和 Linux(bash/sh 应该表现类似)。
当您按 Ctrl+C 时,在当前终端的前台运行的所有程序都会收到信号 SIGINT。在你的情况下,它是你的主要 python 进程和由 os.system 产生的所有进程。
由 os.system 产生的进程然后终止它们的执行。通常当 python 脚本收到 SIGINT 时,它会引发 KeyboardInterrupt 异常,但您的主进程会忽略 SIGINT,因为os.system(). Pythonos.system() 调用标准 C 函数 system(),这使得调用进程忽略 SIGINT ( man Linux / man Mac OS X )。
所以你的python线程都没有收到SIGINT,只有子进程得到它。
当您删除 os.system() 调用时,您的 Python 进程将停止忽略 SIGINT,您将获得KeyboardInterrupt.
您可以替换os.system("sleep 10")为subprocess.call(["sleep", "10"]). subprocess.call()不会让您的进程忽略 SIGINT。