python - 如何在 Python 中安全地停止无限循环?

标签 python infinite-loop

我有一个脚本,它运行一个无限循环并向数据库添加内容,并执行我不能中途停止的操作,所以我不能只按 Ctrl+C 并停止它。

我希望能够以某种方式停止 while 循环,但让它在停止之前完成最后一次迭代。

让我澄清一下:

我的代码看起来像这样:

while True:
    do something
    do more things
    do more things

我希望能够在结束或开始时中断 while 循环,但不能在做事之间中断,因为那样会很糟糕。

而且我不希望它在每次迭代后询问我是否要继续。


感谢您的出色回答,我非常感激,但我的实现似乎不起作用:

def signal_handler(signal, frame):
    global interrupted
    interrupted = True

class Crawler():
    def __init__(self):
        # not relevant

    def crawl(self):
        interrupted = False
        signal.signal(signal.SIGINT, signal_handler)
        while True:
            doing things
            more things

            if interrupted:
                print("Exiting..")
                break

当我按下 Ctrl+C 时,程序一直忽略我。

最佳答案

您需要做的是捕获中断,设置一个标志说明您被打断了,然后继续工作直到检查标志(在每个循环结束时)。因为 python 的 try-except 构造会放弃当前运行的循环,所以您需要设置一个适当的信号处理程序;它会处理中断,然后让 python 从它停止的地方继续。方法如下:

import signal

import time   # For the demo only

def signal_handler(signal, frame):
    global interrupted
    interrupted = True

signal.signal(signal.SIGINT, signal_handler)


interrupted = False
while True:
    print("Working hard...")
    time.sleep(3)
    print("All done!")

    if interrupted:
        print("Gotta go")
        break

注意事项:

  1. 从命令行使用它。在 IDLE 控制台中,它会破坏 IDLE 自己的中断处理。

  2. 更好的解决方案是在循环期间“阻止”KeyboardInterrupt,并在需要轮询中断时解除阻止。这是一些 Unix 风格的特性,但不是全部,因此 python does not support it (见第三条“通则”)

  3. OP 希望在一个类中执行此操作。但是中断函数由信号处理系统调用,有两个参数:信号编号和指向堆栈帧的指针——没有地方可以让 self 参数访问类对象。因此,设置标志的最简单方法是使用全局变量。您可以通过使用闭包(即,在 __init__() 中动态定义信号处理程序)来装配指向本地上下文的指针,但坦率地说,除非由于 multi 而无法使用全局,否则我不会打扰-线程或其他。

警告:如果您的进程处于系统调用的中间,处理信号可能会中断系统调用。所以这可能对所有应用程序都不安全。更安全的替代方案是 (a) 不依赖信号,而是在每次循环迭代结束时使用非阻塞读取(并键入输入而不是按 ^C); (b) 使用线程或进程间通信将 worker 与信号处理隔离开来;或 (c) 执行实际 signal blocking 的工作,如果您使用的是具有它的操作系统。所有这些都在某种程度上依赖于操作系统,所以我就此打住。

关于python - 如何在 Python 中安全地停止无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32922909/

相关文章:

c - 如何使 C 程序停止任何用户输入的循环?

c - 为什么服务器在关闭客户端连接时进入无限循环

python - 从多个 pyodbc 数据库查询结果构造一个大的 json 响应

python - 有没有办法使用 Python 将窗口移动到另一个监视器?

python - 最大 GAE任务队列处理率

c++ - C++中的连续线程

python - 在Python中使用循环和数组更改条件

Python/PyParsing : Difficulty with setResultsName

c - 为什么这段代码永远循环?

haskell - 类型缩减无限循环