如何使我的代码可停止? (不杀/打断)

Posted

技术标签:

【中文标题】如何使我的代码可停止? (不杀/打断)【英文标题】:How to make my code stopable? (Not killing/interrupting) 【发布时间】:2019-07-11 02:06:45 【问题描述】:

我问这个问题的范围更广,因为我现在没有面临这个具体问题,但我想知道将来如何做。

如果我有一个长时间运行的 python 脚本,那么它应该一直在做一些事情(如果有帮助,可能是一个无限循环)。通过在终端上运行python main.py 命令来启动代码。

代码没有结尾,所以不会有sys.exit()

我不想使用 KeyboardInterrupt,也不想终止任务。因为这些选项很突然,而且您无法准确预测何时停止代码.

当我最终决定终止代码时,有没有办法“温和地”终止代码?例如使用另一个命令、准备课程或运行另一个脚本?

这方面的最佳做法是什么?

PS.:请记住,我是新手编码员。

编辑: 我正在添加一些通用代码,以使我的问题更清楚。

import time,csv

import GenericAPI

class GenericDataCollector:
    def __init__(self):
        self.generic_api = GenericAPI()

    def collect_data(self):
        while True: #Maybe this could be a var that is changed from outside of the class?
            data = self.generic_api.fetch_data() #Returns a JSON with some data
            self.write_on_csv(data)
            time.sleep(1)

    def write_on_csv(self, data):
        with open('file.csv','wt') as f:
            writer = csv.writer(f)
            writer.writerow(data)

def run():
    obj = GenericDataCollector()
    obj.collect_data()

if __name__ == "__main__":
    run()

在这种特殊情况下,该类正在从一些通用 API(以 JSON 格式提供)收集数据,并将其写入 csv 文件,处于无限循环中。我如何编写一种方法(方法?)来停止它(当被调用时,如此意外),而不会突然中断(Ctrl+C 或终止任务)。

【问题讨论】:

当您有实际用例时请询问。不同的情况需要非常不同的解决方案。 您是否要在某个步骤“暂停”代码? @MadPhysicist 我添加了一个通用示例,如果有帮助的话。 @new-dev-123 不是真的。更像是结束这个脚本,但只要我决定,如果我不这样做,就永远运行。 (然而,轻轻地) @ZeCarioca 我的解决方案有帮助吗?还是我错过了什么? 【参考方案1】:

我建议使用signal 模块。这允许您处理信号中断 (SIGINT) 并在退出前清理程序。以如下代码为例:

import signal

running = True

def handle(a, b):
    global running
    running = False

# catch the SIGINT signal and call handle() when the process
# receives it
signal.signal(signal.SIGINT, handle)

# your code here
while running:
    pass

您仍然可以使用Ctrl+C 退出,但您放入 while 循环的内容不会被中途截断。

【讨论】:

@U10-Forward 我有。他们正在寻求一种在无限循环中不突然终止程序的方法。他们要求不要使用 KeyBoardInterrupt,但是您实际上可以询问,只要您处理 SIGINT 信号。 我想这可能是我正在寻找的。不过我有几个问题:a)如果我使用global running,计算机中的任何类/函数都可以找到那个确切的变量吗? b) SIGINT 是 Ctrl+C 信号吗? c) 我可以把它翻译成stop_script.py(而不是ctrl+c),这样我就可以运行它,它会停止我的第一个脚本吗?像global runningrunning = False 这样的东西可以吗? @ZeCarioca 全局将在您的 python 程序中可见。我不建议使用全局变量。如果你在一个对象中运行它,我会修改对象内部的一些属性。就信号而言,Ctrl+C 向程序发送SIGINT。但是,您也可以发送 SIGINT 以及其他任何内容。例如,kill <pid> 也会发送SIGINT。您可以阅读有关 POSIX 信号 here @ZeCarioca 如果这是您将使用的,您能否将我的解决方案标记为正确?谢谢。 这不是我真正想要的,但它肯定回答了我发布的问题。我想我稍后会发布一个新问题。谢谢。【参考方案2】:

基于@Calder White,这个怎么样(未测试):

import signal
import time,csv
import GenericAPI

class GenericDataCollector:
   def __init__(self):
     self.generic_api = GenericAPI()
     self.cont = True

   def collect_data(self):
     while self.cont:
       signal.signal(signal.SIGINT, self.handle)
       data = self.generic_api.fetch_data() #Returns a JSON with some data
       self.write_on_csv(data)
       time.sleep(1)

   def handle(self):
     self.cont = False

   def write_on_csv(self, data):
     with open('file.csv','wt') as f:
       writer = csv.writer(f)
       writer.writerow(data)

def run():
  obj = GenericDataCollector()
  obj.collect_data()

if __name__ == "__main__":
  run()

【讨论】:

以上是关于如何使我的代码可停止? (不杀/打断)的主要内容,如果未能解决你的问题,请参考以下文章

CMake Release 使我的代码停止正常工作

php include_once 使我的代码停止运行

如何使我的自定义 ViewModifier 仅适用于 SwiftUI 中符合(可识别和视图)的内容/视图?

代码未通过安全检查,如何使我的参数绑定更好?

如何使我的当前EXP整数在重装后不重置为0

如何使我的 xml 代码适合所有设备