Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在CTRL+;C在python中被按下_Python_Loops - Fatal编程技术网

如何在CTRL+;C在python中被按下

如何在CTRL+;C在python中被按下,python,loops,Python,Loops,我是python新手,我遇到了以下问题。 我有一个脚本,可以逐个处理文件,并根据输入文件名将输出写入单独的文件。有时我需要中断脚本,但我希望让它完成当前文件的处理,然后终止(以避免结果文件信息不完整)。如何在python中编写这种行为 这是我试过的 a) 试除块 x = 1 print "Script started." while True: try: print "Processing file #",x,"started...&quo

我是python新手,我遇到了以下问题。 我有一个脚本,可以逐个处理文件,并根据输入文件名将输出写入单独的文件。有时我需要中断脚本,但我希望让它完成当前文件的处理,然后终止(以避免结果文件信息不完整)。如何在python中编写这种行为

这是我试过的

a) 试除块

x = 1
print "Script started."
while True:
 try:
  print "Processing file #",x,"started...",
  # do something time-cosnuming
  time.sleep(1)
  x += 1
  print " finished."
 except KeyboardInterrupt:
  print "Bye"
  print "x=",x
  sys.exit()

sys.exit()
输出:

Script started.
Processing file # 1 started...  finished.
Processing file # 2 started...  finished.
Processing file # 3 started... Bye
x= 3
Script started.
Processing file # 1 started...  finished.
Processing file # 2 started...  finished.
Processing file # 3 started...

Exiting by CTRL+C.
迭代#3没有优雅地完成

b) 系统异常钩子

OriginalExceptHook = sys.excepthook
def NewExceptHook(type, value, traceback):
global Terminator
    Terminator = True
    if type == KeyboardInterrupt:
        #exit("\nExiting by CTRL+C.")   # this line was here originally
        print("\n\nExiting by CTRL+C.\n\n")
    else:
        OriginalExceptHook(type, value, traceback)
sys.excepthook = NewExceptHook

global Terminator
Terminator = False

x = 1
while True:
  print "Processing file #",x,"started...",
  # do something time-cosnuming
  time.sleep(1)
  x += 1
  print " finished."
  if Terminator:
   print "I'll be back!"
   break

print "Bye"
print "x=",x
sys.exit()
输出:

Script started.
Processing file # 1 started...  finished.
Processing file # 2 started...  finished.
Processing file # 3 started... Bye
x= 3
Script started.
Processing file # 1 started...  finished.
Processing file # 2 started...  finished.
Processing file # 3 started...

Exiting by CTRL+C.
迭代#3没有优雅地完成

UPD#1 @mguijarr,我稍微修改了代码如下:

import time, sys

x = 1
print "Script started."
stored_exception=None

while True:
    try:
        print "Processing file #",x,"started...",
        # do something time-cosnuming
        time.sleep(1)
        print "Processing file #",x,"part two...",
        time.sleep(1)
        print " finished."
        if stored_exception:
            break
        x += 1
    except KeyboardInterrupt:
        print "[CTRL+C detected]",
        stored_exception=sys.exc_info()

print "Bye"
print "x=",x

if stored_exception:
    raise stored_exception[0], stored_exception[1], stored_exception[2]

sys.exit()
输出是(在Win7-64位上使用“Python 2.7.6::Anaconda 2.0.0(64位)”进行测试):

输出为:

Script started.
Processing file # 1 1001 started...
Processing file # 1 1004 part two...
 finished. 1 1006
Processing file # 2 2001 started...
Processing file # 2 2004 part two...
[CTRL+C detected] Processing file # 2 2001 started...
Processing file # 2 2004 part two...
 finished. 2 2006
Bye
x= 2
y= 2007
Traceback (most recent call last):
  File "test2.py", line 20, in <module>
    time.sleep(1)
KeyboardInterrupt
脚本已启动。
已开始处理文件#1 1001。。。
正在处理文件#1 1004第二部分。。。
完成了。1 1006
正在处理文件#2 2001已开始。。。
正在处理文件#2 2004第二部分。。。
[CTRL+C检测到]已开始处理文件#2 2001。。。
正在处理文件#2 2004第二部分。。。
完成了。2 2006
拜伊
x=2
y=2007
回溯(最近一次呼叫最后一次):
文件“test2.py”,第20行,在
时间。睡眠(1)
键盘中断

我只需要使用一个异常处理程序,它将捕获
键盘中断
和 存储异常。然后,在迭代完成时,如果出现异常 正在挂起,我将中断循环并重新引发异常(以允许正常异常 处理发生的机会)

这是可行的(使用Python 2.7进行了测试):

编辑:正如在评论中所发现的,这个答案对于原始海报来说并不令人满意,下面是一个基于线程的解决方案:

import time
import sys
import threading

print "Script started."

class MyProcessingThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        print "Processing file #",x,"started...",
        # do something time-cosnuming
        time.sleep(1)
        print " finished."

for x in range(1,4):
    task = MyProcessingThread()
    task.start()
    try:
        task.join()
    except KeyboardInterrupt:
        break

print "Bye"
print "x=",x

sys.exit()

您可以编写一个信号处理函数

import signal,sys,time                          
terminate = False                            

def signal_handling(signum,frame):           
    global terminate                         
    terminate = True                         

signal.signal(signal.SIGINT,signal_handling) 
x=1                                          
while True:                                  
    print "Processing file #",x,"started..." 
    time.sleep(1)                            
    x+=1                                     
    if terminate:                            
        print "I'll be back"                 
        break                                
print "bye"                                  
print x
按Ctrl+c发送一个SIGINT中断,该中断将输出:

Processing file # 1 started...
Processing file # 2 started...
^CI'll be back
bye
3

我觉得创建一个具有处理用户异常的状态的类要优雅一些,因为我不必处理不能跨不同模块工作的全局变量

import signal
import time

class GracefulExiter():

    def __init__(self):
        self.state = False
        signal.signal(signal.SIGINT, self.change_state)

    def change_state(self, signum, frame):
        print("exit flag set to True (repeat to exit now)")
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        self.state = True

    def exit(self):
        return self.state


x = 1
flag = GracefulExiter()
while True:
    print("Processing file #",x,"started...")
    time.sleep(1)
    x+=1
    print(" finished.")
    if flag.exit():
        break

这段代码看起来还可以,但行为异常。请参阅问题的更新。是否确实已重新启动?我认为异常只是搞乱了stdout,因为它被缓冲了(删除print语句末尾的“,”看起来确实如此。请参阅问题中的更新代码。我也不明白为什么会这样。请注意,在
x
递增之前按Ctrl-C,然后启动另一个循环,然后测试存储的异常和中断。还请注意,如果异常中断代码,则不能简单地继续前面的计算。您希望延迟中断,因此使用信号之类的东西似乎是唯一的方法。如果您不想得到不完整的结果,而不是等待结果,那么在Ctrl-C上丢弃当前文件也更自然。在这种情况下,你不需要任何特别的东西。捕获键盘中断后,只需清理当前文件。您的代码真的允许当前迭代优雅地完成吗?我也不能重现你的行为:我看不到在按下CTRL+C后打印的“再见”。只是例外信息。(我在win7-64位上使用“Python2.7.6::Anaconda 2.0.0(64位)”。@anandr,它是从我的终端复制的精确输出。我在linuxI上使用Python2.7.7,我不知道如何添加大代码块来评论,所以我更新了您的答案,以演示我在运行代码时看到的内容。这应该是公认的答案,它正是OP试图实现的。
import signal
import time

class GracefulExiter():

    def __init__(self):
        self.state = False
        signal.signal(signal.SIGINT, self.change_state)

    def change_state(self, signum, frame):
        print("exit flag set to True (repeat to exit now)")
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        self.state = True

    def exit(self):
        return self.state


x = 1
flag = GracefulExiter()
while True:
    print("Processing file #",x,"started...")
    time.sleep(1)
    x+=1
    print(" finished.")
    if flag.exit():
        break