如何让用户在预定义点暂停python脚本?

如何让用户在预定义点暂停python脚本?,python,Python,假设我有很多工作要做,所以我想给用户暂停和/或停止工作的选项。 但我不想以不一致的状态结束,因此我只能在程序中的某些点暂停并退出 我将如何实现一个user\u requested\u pause()方法,我可以使用如下方法 对于某些非常大列表中的项目: 你工作吗 #不能停在这里 做更多的工作 #现在我们可以停下来了。 如果用户请求暂停(): #询问用户如何继续,然后以一致状态继续或退出 我考虑过只使用ctrl+c,但是键盘中断可以在任何时候发生 理想情况下,我会检查stdin上是否有可用的输入

假设我有很多工作要做,所以我想给用户暂停和/或停止工作的选项。 但我不想以不一致的状态结束,因此我只能在程序中的某些点暂停并退出

我将如何实现一个
user\u requested\u pause()
方法,我可以使用如下方法

对于某些非常大列表中的项目:
你工作吗
#不能停在这里
做更多的工作
#现在我们可以停下来了。
如果用户请求暂停():
#询问用户如何继续,然后以一致状态继续或退出

我考虑过只使用ctrl+c,但是
键盘中断可以在任何时候发生

理想情况下,我会检查
stdin
上是否有可用的输入,但我还没有找到这样做的方法
read()
如果没有输入,即使用户不希望程序暂停,也会阻塞程序

编辑:我解决了它如下:

导入信号
请求暂停=错误
def处理器(信号、帧):
请求全局暂停
pause_requested=True
对于某些非常大列表中的项目:
你工作吗
做更多的工作
如果请求暂停,请执行以下操作:
#询问用户如何继续,然后以一致状态继续或退出
请求暂停=错误

您可以查看该库。特别是如果你有一个捕捉键盘输入的功能。

你可以通过让处理程序设置一个标志来告诉程序暂停并等待输入来使用它。

你可以使用多线程来有一个单独的线程来做工作,并定期检查状态变量
请求的\u pause
。然后,主线程在请求使用
input()
的循环中运行,并在有条目时相应地设置
请求的\u pause

如果希望在没有用户干预的情况下继续执行(而不是默认情况下暂停需要用户重新启动),则最好的解决方案需要使用辅助线程,协同程序,或接受用户输入并设置某种标志来通知主处理线程暂停的进程。这可以通过多种方式实现,但我将演示仅使用python标准库和内置函数。其他方法可能更灵活(如检测特定按键或使用图形界面而不是命令行),但会很快遇到兼容性问题,因为检测硬件输入通常是通过GUI库完成的,并且系统之间通常略有不同。像这样的一些库相当不错,但即使是这个库也有一个警告(在linux上需要root)

使用线程等待
input()
函数的示例代码(用户按enter键):


由于纯python的一些限制,这不是一个完美的解决方案,因为线程(即使它是守护进程)在程序结束时不会退出,因为它仍在等待用户输入。这要求您按enter键终止程序(尽管所有工作都会很好地完成,解释器将在文件末尾等待)。通过打印语句和一些额外的控制逻辑附加的用户说明可以使这一点更好,但不会在很大程度上改变功能。另一个选项是在主文件中的循环中放置一个
try:except:
,该循环设置/清除一个标志,执行主工作的工作线程每隔一段时间检查一次该标志。

读取控制台以获取输入,这将暂停执行。然后忽略输入。
KeyboardInterrupt
只会在用户干预时发生,因此,为什么不捕获该错误,然后提出一个问题:用户是想完全停止执行还是只是暂停?请求
input()
本身会暂停代码,因为
input
正在阻塞。我已经写了为什么我不想只使用read():它需要用户推进每一次迭代。不可行。至于ctrl+c:如果用户在
do_work()
do_more_work
之间按下它会怎么样?那我的状态就不稳定了!我在哪里说的
read()
?你已经使用过两次了,我一次也没有。为什么它会要求用户推进每次迭代?如果你只是对解决方案中涉及到的内容有预先设想的想法,那么问一个问题是毫无意义的。阅读的东西是针对dcg的。我不希望用户必须推进每次迭代。
import threading, time

class user_input_thread(threading.Thread):
    def __init__(self, event_obj):
        super().__init__()
        self.daemon = True
        self.event_obj = event_obj

    def run(self):
        while True:

            self.event_obj.wait() #wait for the user to resume processing from main thread
            print('process resumed')
            input('press enter to pause\n') #use raw_input() for python 2.x
            print('process will pause')
            self.event_obj.clear() #clear the flag forcing processing to stop

def main_work(event_obj, *args):
    for x in range(10):
        if not event_obj.is_set():
            input('press enter to resume') #use raw_input() for python 2.x
            event_obj.set()
        time.sleep(2) #heavy computation that can't be interrupted
        print('done with task {}'.format(x))

if __name__ == '__main__':
    event_obj = threading.Event() #work starts paused
    user_input_thread(event_obj).start()
    main_work(event_obj)