我遇到了一个非常奇怪的问题,这让我想知道我是否理解异常处理。
我有一个代码(我将在最后发布)看起来或多或少像这样:
try:
doSomething()
finally:
print 'bye'
当我通过ctrl + c退出程序时,finally子句中的代码没有被执行。
更糟糕的是,现在考虑以下事项:
try:
doSomething()
except: # this could be replaced by except Exception, it doesn't matter
print 'something'
finally:
print 'bye'
现在不执行except子句中的代码..但finally子句中的代码是!
我意识到这必须是doSomething()执行的代码的错误。但我的问题是,它怎么可能呢?我认为我们可以100%确信最终的条款总是被执行。
这是真正的代码。它运行在树莓派3上。它是对here找到的代码的改编。
import RPi.GPIO as GPIO, time
GPIO.setmode(GPIO.BCM)
# Define function to measure charge time
def RCtime (PiPin):
# Discharge capacitor
GPIO.setup(PiPin, GPIO.OUT)
GPIO.output(PiPin, GPIO.LOW)
time.sleep(.1)
time1 = time.time()
GPIO.setup(PiPin, GPIO.IN)
if (GPIO.input(PiPin) == GPIO.LOW):
GPIO.wait_for_edge(PiPin, GPIO.RISING, timeout=1000)
time_elap = time.time()-time1
return time_elap*1e3
# Main program loop
try:
while True:
print RCtime(4) # Measure timing using GPIO4
except Exception:
print '---------got ya-----------------'
finally:
print '---Finaly---'
GPIO.cleanup() # this ensures a clean exit
更具体地说,当程序在GPIO.wait_for_edge(PiPin, GPIO.RISING, timeout=1000)
行等待时,会出现所描述的行为。
答案 0 :(得分:0)
如果您的代码不处理KeyboardInterrupt
异常,系统必须这样做:这意味着它会杀死代码。相反,如果你有一个异常处理程序,你的代码将接管,离开循环,然后执行finally
块。
答案 1 :(得分:0)
嗯,这似乎是与RPi.GPIO处理信号的方式有关的错误(例如KeyboardInterrupt)。该模块调用用c编写的一些函数。该函数有点捕获KeyboardInterrupt并抛出异常,但它没有正确执行。两个例外不是只有一个例外,而是“堆叠”。因此,我的代码中的异常之后运行的第一件事将由第二个异常终止。如果我不包含except块,则finally块在第一个异常之后执行,并由第二个异常终止。如果我包含一个except块,它会尝试在第一个异常之后运行,由于第二个异常而失败,然后它转到finally块。 我只找到一个人forum来处理类似的问题。
在我之前的实验之后,我很好奇这是如何工作的 input()[https://svn.python.org/projects/python/trunk/Parser/myreadline.c]。我用raw_input()替换了sem.acquire()并运行了同样的东西 试验。现在内部异常真的被采用,所以它像OP一样工作 预期。但是,例外是KeyboardInterrupt,而不是特殊的 IPC模块的例外情况。 所以我在源代码中查看了它们是如何做到的: 代码在Parser / myreadline.c中。
此函数中的输入代码调用PyErr_CheckSignals()和 PyOS_InterruptOccurred()用于正确处理中断。所以 OP似乎应该做类似的事情。 Onl; y提供自定义 错误你将不得不做一些其他的东西。我不知道是什么,但也许 调用PyErr_SetString就足够了,因为它可能会覆盖 KeyboardInterrupt东西。