要求 python 从 bash 停止(受控)的有效方法(/tmp/stop?)
Efficient way to ask python to stop (controlled) from bash (/tmp/stop?)
从 Bash 脚本请求 Python 程序停止(以受控方式)的最有效方法是什么(就轮询开销而言)。在 python 方面,我想要一个函数(尽可能快地执行),当请求停止时 returns 为真,否则为假。如果为真,我们保存我们的工作,释放资源并退出。
对于一些简单的工具,我实现了以下内容:
- 在 bash 我做了一个
touch /tmp/stop
- 我的 Python 程序经常轮询
/tmp/stop
确实存在。如果它存在,则以受控方式退出。
- 我的 bash 脚本等待(循环 - 睡眠 - ps)直到相关进程停止。
此解决方案有效,但轮询此文件很可能不是最有效的方法。
是否有其他开销较小的选项(就 Python 轮询时间而言)?
UNIX 信号机制将是一个很好的选择。您不需要任何临时文件,轮询开销基本上为零。
您可以像这样优雅地关闭以下 python 程序:kill -USR1 $pid
.
import signal
import time
import sys
please_stop = False
def setup_signal():
def handler(x,y):
global please_stop
please_stop = True
signal.signal(signal.SIGUSR1, handler)
def main_task():
for i in range(10):
print "Working hard on iteration #%d"%i
time.sleep(1)
if please_stop:
print "Stopping now"
sys.exit(0)
setup_signal()
main_task()
您可以向 python 进程发送中断信号 (SIGINT)。当您按下 Ctrl+C:
时,您的 shell 会发送相同的信号
在 Bash 中看起来像这样:
python my_script.py & # start the script in background
pyscript_pid=$! # store the python interpreter' PID
sleep(5) # pause 5 seconds
kill -s SIGINT $pyscript_pid # send the SIGINT signal to the process
而在 Python 中,您只需捕获当解释器接收到 SIGINT 信号时抛出的 KeyboardInterrupt
异常:
try:
print ("I'm still running...")
# do something useful, but it must be interruptible at any time!
except KeyboardInterrupt:
print ("I'm going to quit now.")
# tidy up...
# ... and exit
虽然在 try 块中被中断时,您不应该做会破坏任何东西的事情,只执行可以被中断或重置为整理代码中最后有效状态的事情。或者,您可以使用 try: ... finally: ...
来确保 finally
块中的代码将始终启动,即使 try
中的代码在 运行.[=17= 时被中断。 ]
您还可以查看 How do I capture SIGINT in Python? 或@Robᵩ 的回答以了解如何捕获所有可能的信号而不仅仅是 SIGINT 以及如何为它们注册事件处理程序而不是使用 try-catch(-finally) , 但这是最简单的方法。
从 Bash 脚本请求 Python 程序停止(以受控方式)的最有效方法是什么(就轮询开销而言)。在 python 方面,我想要一个函数(尽可能快地执行),当请求停止时 returns 为真,否则为假。如果为真,我们保存我们的工作,释放资源并退出。
对于一些简单的工具,我实现了以下内容:
- 在 bash 我做了一个
touch /tmp/stop
- 我的 Python 程序经常轮询
/tmp/stop
确实存在。如果它存在,则以受控方式退出。 - 我的 bash 脚本等待(循环 - 睡眠 - ps)直到相关进程停止。
此解决方案有效,但轮询此文件很可能不是最有效的方法。
是否有其他开销较小的选项(就 Python 轮询时间而言)?
UNIX 信号机制将是一个很好的选择。您不需要任何临时文件,轮询开销基本上为零。
您可以像这样优雅地关闭以下 python 程序:kill -USR1 $pid
.
import signal
import time
import sys
please_stop = False
def setup_signal():
def handler(x,y):
global please_stop
please_stop = True
signal.signal(signal.SIGUSR1, handler)
def main_task():
for i in range(10):
print "Working hard on iteration #%d"%i
time.sleep(1)
if please_stop:
print "Stopping now"
sys.exit(0)
setup_signal()
main_task()
您可以向 python 进程发送中断信号 (SIGINT)。当您按下 Ctrl+C:
时,您的 shell 会发送相同的信号在 Bash 中看起来像这样:
python my_script.py & # start the script in background
pyscript_pid=$! # store the python interpreter' PID
sleep(5) # pause 5 seconds
kill -s SIGINT $pyscript_pid # send the SIGINT signal to the process
而在 Python 中,您只需捕获当解释器接收到 SIGINT 信号时抛出的 KeyboardInterrupt
异常:
try:
print ("I'm still running...")
# do something useful, but it must be interruptible at any time!
except KeyboardInterrupt:
print ("I'm going to quit now.")
# tidy up...
# ... and exit
虽然在 try 块中被中断时,您不应该做会破坏任何东西的事情,只执行可以被中断或重置为整理代码中最后有效状态的事情。或者,您可以使用 try: ... finally: ...
来确保 finally
块中的代码将始终启动,即使 try
中的代码在 运行.[=17= 时被中断。 ]
您还可以查看 How do I capture SIGINT in Python? 或@Robᵩ 的回答以了解如何捕获所有可能的信号而不仅仅是 SIGINT 以及如何为它们注册事件处理程序而不是使用 try-catch(-finally) , 但这是最简单的方法。