发生异常后我可以返回执行 try-block 吗?(目标是少写)例如:
try:
do_smth1()
except:
pass
try:
do_smth2()
except:
pass
对比
try:
do_smth1()
do_smth2()
except:
??? # magic word to proceed to do_smth2() if there was exception in do_smth1
不,你不能那样做。这就是 Python 的语法。一旦你因为异常退出了一个 try-block,就没有办法回来了。
但是for循环呢?
funcs = do_smth1, do_smth2
for func in funcs:
try:
func()
except Exception:
pass # or you could use 'continue'
但是请注意,裸露的except
. 您应该改为捕获特定异常。我捕获它是Exception
因为在不知道方法可能抛出什么异常的情况下,我可以做到这一点。
虽然其他答案和接受的答案都是正确的,并且应该在实际代码中遵循,但为了完整性和幽默,您可以尝试fuckitpy
( https://github.com/ajalt/fuckitpy ) 模块。
您的代码可以更改为以下内容:
@fuckitpy
def myfunc():
do_smth1()
do_smth2()
然后调用myfunc()
会调用do_smth2()
,即使有异常do_smth1())
注意:请不要在任何真实代码中尝试,这是亵渎神灵
您可以实现您想要的,但使用不同的语法。您可以在 try/except 之后使用“finally”块。这样做,无论是否抛出异常,python都会执行代码块。
像这样:
try:
do_smth1()
except:
pass
finally:
do_smth2()
但是,如果您只想在未引发异常的情况下执行 do_smth2(),请使用“else”块:
try:
do_smth1()
except:
pass
else:
do_smth2()
您也可以在 try/except/else/finally 子句中混合它们。玩得开心!
您可以处理此问题的一种方法是使用生成器。与其调用函数,不如让其生成;那么任何消耗生成器的东西都可以将调用它的结果发送回生成器,或者如果生成器失败,则发送一个哨兵:完成上述操作的蹦床可能如下所示:
def consume_exceptions(gen):
action = next(gen)
while True:
try:
result = action()
except Exception:
# if the action fails, send a sentinel
result = None
try:
action = gen.send(result)
except StopIteration:
# if the generator is all used up, result is the return value.
return result
与此兼容的生成器如下所示:
def do_smth1():
1 / 0
def do_smth2():
print "YAY"
def do_many_things():
a = yield do_smth1
b = yield do_smth2
yield "Done"
>>> consume_exceptions(do_many_things())
YAY
请注意,do_many_things()
不调用,它只是产生它们,并代表它调用它们do_smth*
consume_exceptions
你可以遍历你的方法......
for m in [do_smth1, do_smth2]:
try:
m()
except:
pass
仅当 try 块在循环中时,才允许在 'except' 或 'finally' 中使用 'continue'。“继续”将导致循环的下一次迭代开始。
因此,您可以尝试将两个或多个函数放在一个列表中,并使用循环来调用您的函数。
像这样:
funcs = [f,g]
for func in funcs:
try: func()
except: continue
我不认为你想这样做。一般来说,使用try
语句的正确方法是尽可能精确。我认为这样做会更好:
try:
do_smth1()
except Stmnh1Exception:
# handle Stmnh1Exception
try:
do_smth2()
except Stmnh2Exception:
# handle Stmnh2Exception
根据您需要执行此操作的位置和频率,您还可以编写一个为您执行此操作的函数:
def live_dangerously(fn, *args, **kw):
try:
return fn(*args, **kw)
except Exception:
pass
live_dangerously(do_smth1)
live_dangerously(do_smth2)
但正如其他答案所指出的那样,空except
值通常表明您的代码有其他问题。
special_func以避免重复尝试:
def special_func(test_case_dict):
final_dict = {}
exception_dict = {}
def try_except_avoider(test_case_dict):
try:
for k,v in test_case_dict.items():
final_dict[k]=eval(v) #If no exception evaluate the function and add it to final_dict
except Exception as e:
exception_dict[k]=e #extract exception
test_case_dict.pop(k)
try_except_avoider(test_case_dict) #recursive function to handle remaining functions
finally: #cleanup
final_dict.update(exception_dict)
return final_dict #combine exception dict and final dict
return try_except_avoider(test_case_dict)
运行代码:
def add(a,b):
return (a+b)
def sub(a,b):
return (a-b)
def mul(a,b):
return (a*b)
case = {"AddFunc":"add(8,8)","SubFunc":"sub(p,5)","MulFunc":"mul(9,6)"}
solution = special_func(case)
输出如下所示:
{'AddFunc': 16, 'MulFunc': 54, 'SubFunc': NameError("name 'p' is not defined")}
转换为变量:
locals().update(solution)
变量看起来像:
AddFunc = 16, MulFunc = 54, SubFunc = NameError("name 'p' is not defined")
这可以通过exec()
自定义函数、字符串列表和for
循环来完成。
具有以下功能的功能exec()
:
def try_it(string):
try:
exec(string)
print(f'Done: {string}')
except:
print(f'Error. Could not do: {string}')
更多关于 exec():
exec( object )
这个函数支持 Python 代码的动态执行。object必须是字符串或代码对象。
for
字符串和循环的示例列表:
do_smth_list = ['do_smth1()', 'do_smth2()', 'do_smth3()']
for smth in do_smth_list:
try_it(smth)
我可能是错的,这绝对不是最干净的方法,但是您可以将它放在一个while循环中,并将变量设置为true,当它成功运行函数时,它将变量设置为false,而如果它失败它保持变量设置为真。
x = True
while x == True:
try:
do_smth1()
x = False
except:
x = True
pass
这样会发生什么是while循环将继续循环try except部分一次又一次,直到它工作,其中x设置为false并且循环停止
抱歉,如果我没有使用正确的技术术语或编码错误,我对 python 还是很陌生