我可以有一个运行的python脚本(在Windows下)被暂停在中间由用户,并再次恢复当用户决定?
有一个主管理程序,它生成,加载和运行其他python脚本(通过从控制台调用python script.py)。我没有GUI,用户可以通过控制台进行交互。我希望我的主程序能够响应用户暂停/恢复命令的运行脚本。我应该定义一个线程吗?方法是什么?
编辑/更新:
假设我有一个小型的python应用程序,它的前端有各种功能。我有一个在后台运行python脚本的RUN命令。我想实现一个PAUSE功能,暂停正在运行的python脚本。当用户再次命令RUN时,python脚本应该恢复运行运行。使用raw_input()或print()强制用户发出命令。但是在这种情况下,我们不知道用户何时想要中断/暂停/发出命令。所以通常的输入/打印是不可用的。
如果是unix,我会推荐signal,但这里有一个粗略的版本,可以满足您的要求。
import time
while True:
try:
time.sleep(1) # do something here
print '.',
except KeyboardInterrupt:
print 'nPausing... (Hit ENTER to continue, type quit to exit.)'
try:
response = raw_input()
if response == 'quit':
break
print 'Resuming...'
except KeyboardInterrupt:
print 'Resuming...'
continue
按Ctrl+C暂停,按ENTER继续。Ctrl+Break也许可以作为一个残酷的杀戮,但我没有这个键盘上的键。
更健壮的版本可以在管道/套接字,甚至线程上使用select。
您可以通过创建PAUSEFILE
来做一个简单的解决方案。要暂停的脚本可能会定期检查这样的文件是否存在(或内容)。
用户的PAUSE
命令可以创建(或填充适当的内容)这样的文件。
我在一个类似的情况下使用了这种方法,我希望能够暂停我的Python脚本并在以后恢复它们。它们包含像
这样的内容if os.path.isfile(PAUSEFILE):
raw_input('Remove ' + PAUSEFILE + ' and hit ENTER to continue')
在主循环中。
它很讨厌,如果代码真的依赖于它,它可能会被破坏,但对于用例来说,暂停是由用户随机完成的,我想这无关紧要。
PAUSE
命令是简单的touch $PAUSEFILE
。
好的,从我在搜索中看到的,即使有线程,sys.stdin
也会对你不利,无论你如何得到它(input()
,甚至sys.stdin.read()
)。readline()
等),因为它们阻塞了。
相反,把你的管理器程序写成一个套接字服务器或类似的东西。
将脚本编写为生成器,旨在暂停执行(每次遇到yield
时),并依次重复地调用每个脚本的next()
。当脚本完成时,您将得到一个StopIteration
异常。
为了处理命令,编写第二个脚本,连接到管理器程序的套接字并向其发送消息,这将是用户与之交互的控制台接口(稍后,您甚至可以将其升级为GUI,而无需更改其他地方)。
服务器在脚本上运行下一次迭代之前拾取这些命令,如果脚本被用户暂停,则管理器程序在用户告诉它再次运行之前不会对该脚本调用next()
。
我还没有测试过这个,但我认为它会比为外部脚本创建线程或子进程,然后尝试暂停(稍后杀死)它们更好。
这真的超出了我的深度,但也许在后台运行脚本并使用kill -stop
和kill -cont
暂停和继续将工作(假设Linux)?
我不太明白你的方法,但每次用户需要按回车键继续脚本时,你应该使用:
input() #for python 3k
raw_input() #for python 2k
而不将接收到的答案赋值给变量。
我觉得这些回答很粗俗,但也很有趣。
最好的方法是https://stackoverflow.com/a/7184165/2480481使用KeyboardInterrupt
异常。
因为我注意到没有人提到"使用调试器",所以我将这么做。
安装pdb, Python调试器与pip install pdb
。按Ctrl+c使脚本可暂停https://stackoverflow.com/a/39478157/2480481,而不是退出它。
使用调试器(pdb)的主要好处是可以检查变量、值等。这比暂停/继续要强大得多。
还可以添加带有pdb的Ipython接口,以便在应用程序崩溃时进行调试。查看:https://stackoverflow.com/a/14881323/2480481
如果你从windows命令窗口启动python脚本,你可以使用msvcrt.kbhit()作为非阻塞按键检查,如下所示:http://code.activestate.com/recipes/197140-key-press-detection-for-windows-text-only-console-/
您可以在python中使用Pdb
模块。尽管它是一个调试器,但在您的情况下,它可以帮助您在代码中有断点的地方传递并继续。
同样,当你恢复时,你可以看到它暂停的位置和变量的值等。这将非常有帮助。
python debugger - pdb
我一直在寻找这个很长时间。因此我决定自己解决这个问题。下面的代码对我来说很好。
在开始循环之前,简单地为用户打印一条指令行。
这是我的代码-
import time
start = 0
run = True
while run == True:
try :
# Loop Code Snippet
for i in range(start,100):
time.sleep(2)
print(i)
start = i+1
except :
print("""~~~~~~~Code interupted~~~~~~~
n Press 1 to resume
n Press 2 to quit""")
res = input()
if res == "1" :
print("1")
# pass and resume code
pass
if res == "2" :
print("2")
#Save output and quit code
run = False
pass #Safety pass if case user press invalid input
此代码可以通过使用常规的"Ctrl + C"来中断。
这是如何工作的当代码中断时,"键盘中断";抛出错误。由于哪个错误处理程序"Try:Except"将转到Except块(用户可以在其中提供恢复、保存当前输出或退出代码的输入)
对于resume功能,循环的当前位置被保存并反馈到start For循环中。
这里有很多改进之处,期待建议。
您尝试过明显的打印提示符然后从stdin读取一行吗?这将暂停整个脚本。
你在最初的问题中问的不是很清楚,所以如果这不是你想要的,你能解释为什么吗?
在Windows中,您可以暂停/恢复正在运行的Python脚本。在CMD或通过运行命令(Windows+R)键入resmon。找到Python脚本进程并右键单击>Suspend process。这将解锁CPU使用率,但不会解锁RAM。;)
在Linux终端:
sudo pkill -STOP python3
sudo pkill -CONT python3
如果你想在python中做,然后用文本
创建config.ini。[control]
pausescript = False
然后在python脚本中:
from configparser import ConfigParser
config = ConfigParser()
config.read("config.ini")
和脚本中循环的地方:
pauseScript = True
while pauseScript:
config.read("config.ini")
pauseScript = config.getboolean('control', 'pausescript')
if pauseScript:
print("Script paused. Resume by change config setting to False. ",end="r")
time.sleep(0.3)
然后通过在config.ini文件