繁体   English   中英

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

[英]How do I let the user pause a python script at predefined points?

说我有很多工作要做,所以我想让用户选择暂停和/或停止工作。 但是我不希望最终出现一个不一致的状态,所以我只能暂停并退出程序中的某些点。

我如何实现我可以使用的user_requested_pause()方法?

for item in some_very_large_list:
  do_work()
  # can't stop here
  do_more_work()
  # now we could pause.
  if user_requested_pause():
    # ask user how to proceed, then continue or exit with consistent state

我想过只使用ctrl + c但是KeyboardInterrupt可以在任何时候出现。

理想情况下,我会检查stdin上是否有输入,但我还没有找到办法。 read()只是阻塞,如果没有输入会暂停程序,即使用户不想要它。

编辑:我解决了如下:

import signal
pause_requested = False
def handler(signum, frame):
  global pause_requested
  pause_requested = True
for item in some_very_large_list:
  do_work()
  do_more_work()
  if pause_requested:
    # ask user how to proceed, then continue or exit with consistent state
    pause_requested = False

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

您可以通过使处理程序设置一个标志来告诉程序暂停并等待输入,从而可以使用signal模块

您可以使用多线程来创建单独的线程来执行工作,并定期检查状态变量requested_pause 主线程然后在请求使用input()的循环中运行,并在有条目时相应地设置requested_pause

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

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

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)

由于纯python的一些限制,这不是一个完美的解决方案,因为线程(即使它是一个守护进程)不会在程序结束时退出,因为它仍在等待用户输入。 这要求你按Enter键来终止程序(尽管所有的工作都会很好,而解释器只会在文件末尾等待)。 通过print语句和一些额外的控制逻辑的附加用户指令可以使这更好,但不会在很大程度上改变功能。 另一种选择只是try: except:在主文件的循环中设置/清除一个标志,一个工作线程执行主要工作经常检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM