要求 python 从 bash 停止(受控)的有效方法(/tmp/stop?)

Efficient way to ask python to stop (controlled) from bash (/tmp/stop?)

从 Bash 脚本请求 Python 程序停止(以受控方式)的最有效方法是什么(就轮询开销而言)。在 python 方面,我想要一个函数(尽可能快地执行),当请求停止时 returns 为真,否则为假。如果为真,我们保存我们的工作,释放资源并退出。

对于一些简单的工具,我实现了以下内容:

此解决方案有效,但轮询此文件很可能不是最有效的方法。

是否有其他开销较小的选项(就 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) , 但这是最​​简单的方法。