我正在 Windows 上用 Python 3 编写一些代码,如下所示:
try:
do something that takes a long time
(training a neural network in TensorFlow, as it happens)
except KeyboardInterrupt:
print('^C')
print a summary of results
still useful even if the training was cut short early
如果直接从控制台使用
python foo.py
运行,效果非常好。
但是,如果对 Python 的调用是在批处理文件中,它最终会执行上述所有操作,但仍然会向控制台发送“终止批处理作业”提示。
有办法阻止这种情况发生吗?通过在Python中完全吃掉^C,直接跳出批处理文件还是其他方式?
在批处理文件中使用
break
(更多信息)命令,这将禁用 CTRL+C 停止文件
编辑:根据this site的break命令
较新版本的 Windows(Windows ME、Windows 2000、Windows XP 及更高版本)仅包含此命令以实现向后兼容性,关闭中断没有任何效果。
我亲自测试了这一点,并且可以确认,当我找到解决方法时我会进行编辑
编辑#2:如果您可以有第二个批处理脚本来运行
start "" /b /wait cmd /c "yourfile.bat"
,但是众所周知,这会导致其他嵌套批处理文件出现故障
禁用 Ctrl+C 的标志由子进程继承,因此 Python 将不再引发键盘中断。另外,如果从控制台的读取被 Ctrl+C 中断而没有从 CRT 获取 SIGINT,那么 Python 中仍然存在错误。 Python 脚本应通过 ctypes 手动启用 Ctrl+C。使用导入ctypes; kernel32 = ctypes.WinDLL('kernel32', use_last_error=True);成功= kernel32.SetConsoleCtrlHandler(无,假)
编辑#3正如Eryksyn(在评论中)所指出的,您可以使用cytpes来启用它;
import ctypes;
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True); success = kernel32.SetConsoleCtrlHandler(None, False)
编辑#4:我想我找到了它,试试这个(虽然它可能不起作用)你可以使用threading导入吗?
import time
from threading import Thread
def noInterrupt():
for i in xrange(4):
print i
time.sleep(1)
a = Thread(target=noInterrupt)
a.start()
a.join()
print "done"
Windows 允许您对当前进程关闭 Ctrl-C,这也会抑制操作系统中 Ctrl-C 已发送到当前进程的记录。
您可以使用上下文管理器完全忽略 Ctrl-C,如下所示:
class Ignore_Ctrl_C:
def __enter__(self):
ctypes.windll.kernel32.SetConsoleCtrlHandler(None, True)
return self
def __exit__(self, exc_type, exc_value, traceback):
ctypes.windll.kernel32.SetConsoleCtrlHandler(None, False)
with Ignore_Ctrl_C():
do_something_that_requires_Ctrl_C_off()
如果您有 main() 函数,您可以尝试使用多进程模块将其作为单独的进程运行,并让顶级进程在等待 main() 完成时使用 Ignore_Ctrl_C() 。 我希望任何进入子进程的 Ctrl-C 最终都不会与顶级进程相关联,并且您的批处理文件不应该要求终止。
或者,如果您不能或不想摆弄您的 python 程序,您可以在“运行程序”程序中使用 Ignore_Ctrl_C() 来启动您的程序并等待,而不是直接运行您的程序的批处理文件就完成了。