如何使我的代码可停止? (不杀/打断)
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 running
和running = 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()
【讨论】:
以上是关于如何使我的代码可停止? (不杀/打断)的主要内容,如果未能解决你的问题,请参考以下文章