send_signal(signal.SIGINT) 不工作?
send_signal(signal.SIGINT) not working?
我创建了两个简单的脚本:
script.py:
import time
import sys
import signal
try:
print('i am running')
time.sleep(10)
print('i am done')
except KeyboardInterrupt:
print("you don't like me??")
和test.py:
import subprocess
import signal
from threading import Thread
import time
import os
p = subprocess.Popen('python script.py', shell=True)
t = Thread(target=p.wait)
t.start()
print('sleeping')
time.sleep(2)
print('interrupt')
p.send_signal(signal.SIGINT)
#p.send_signal(signal.SIGTERM)
t.join()
print('process finished')
如果我 运行 test.py(在 ubuntu 上),预期结果将是:
sleeping
i am running
interrupt
you don't like me??
process finished
SIGINT 似乎被忽略了:
sleeping
i am running
interrupt
i am done
process finished
SIGTERM 按预期终止进程。但是没有引发 KeyboardInterrupt。
即使我将以下行添加到 script.py
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
signal.signal(signal.SIGINT, signal_handler)
似乎没有收到 SIGINT。
但是,当我自己按下 C+CTRL 时,收到了一个 SIGINT。但这对我来说不是一个选择,因为 SIGINT 必须是时间触发的。
有人知道为什么会这样吗?
干杯,
托马斯
(我在我的示例中删除了线程的使用,因为除了更多代码行之外,它没有向示例添加任何内容)
这与信号在进程组中的处理方式有关,您可能会发现 this other SO answer 答案很有帮助。
import subprocess
import signal
import time
import os
p = subprocess.Popen('python script.py', shell=True, preexec_fn=os.setsid)
print('sleeping')
time.sleep(2)
os.killpg(os.getpgid(p.pid), signal.SIGINT)
print('interrupt')
p.wait()
print('process finished')
这会产生预期的结果:
andy@batman[14:58:04]:~/so$ python test.py
sleeping
i am running
interrupt
you don't like me??
process finished
信号由进程组处理,因此从进程组内的进程发送信号并不像您想象的那样有效。
有趣的是,如果你不使用 shell=True
(which you shouldn't use if you can avoid it),它工作得很好。
import subprocess
import signal
import time
import os
p = subprocess.Popen(['python', 'script.py'])
print('sleeping')
time.sleep(2)
p.send_signal(signal.SIGINT)
print('interrupt')
p.wait()
print('process finished')
因此,老实说,这个答案有点废话,因为我可以向您展示两个表面上有效的东西,但并不能真正解释为什么。
我创建了两个简单的脚本:
script.py:
import time
import sys
import signal
try:
print('i am running')
time.sleep(10)
print('i am done')
except KeyboardInterrupt:
print("you don't like me??")
和test.py:
import subprocess
import signal
from threading import Thread
import time
import os
p = subprocess.Popen('python script.py', shell=True)
t = Thread(target=p.wait)
t.start()
print('sleeping')
time.sleep(2)
print('interrupt')
p.send_signal(signal.SIGINT)
#p.send_signal(signal.SIGTERM)
t.join()
print('process finished')
如果我 运行 test.py(在 ubuntu 上),预期结果将是:
sleeping
i am running
interrupt
you don't like me??
process finished
SIGINT 似乎被忽略了:
sleeping
i am running
interrupt
i am done
process finished
SIGTERM 按预期终止进程。但是没有引发 KeyboardInterrupt。
即使我将以下行添加到 script.py
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
signal.signal(signal.SIGINT, signal_handler)
似乎没有收到 SIGINT。
但是,当我自己按下 C+CTRL 时,收到了一个 SIGINT。但这对我来说不是一个选择,因为 SIGINT 必须是时间触发的。
有人知道为什么会这样吗?
干杯, 托马斯
(我在我的示例中删除了线程的使用,因为除了更多代码行之外,它没有向示例添加任何内容)
这与信号在进程组中的处理方式有关,您可能会发现 this other SO answer 答案很有帮助。
import subprocess
import signal
import time
import os
p = subprocess.Popen('python script.py', shell=True, preexec_fn=os.setsid)
print('sleeping')
time.sleep(2)
os.killpg(os.getpgid(p.pid), signal.SIGINT)
print('interrupt')
p.wait()
print('process finished')
这会产生预期的结果:
andy@batman[14:58:04]:~/so$ python test.py
sleeping
i am running
interrupt
you don't like me??
process finished
信号由进程组处理,因此从进程组内的进程发送信号并不像您想象的那样有效。
有趣的是,如果你不使用 shell=True
(which you shouldn't use if you can avoid it),它工作得很好。
import subprocess
import signal
import time
import os
p = subprocess.Popen(['python', 'script.py'])
print('sleeping')
time.sleep(2)
p.send_signal(signal.SIGINT)
print('interrupt')
p.wait()
print('process finished')
因此,老实说,这个答案有点废话,因为我可以向您展示两个表面上有效的东西,但并不能真正解释为什么。