Python中更简洁的try except写法

5

假设我有三个不同的调用名称为 somethingsomething1something2

现在,我正在这样调用它:

try:
   something
   something1
   something2
except Keyerror as e:
   print e

请注意,在上面的代码中,如果某些操作失败,则不会执行something1和something2等后续操作。
期望的结果是:
try:
    something
except KeyError as e:
    print e
try:
    something1
except KeyError as e:
    print e
try:
    something2
except KeyError as e:
    print e

如何在不使用太多try except块的情况下实现上述代码?
编辑:
所以,我选择的答案有效。但其他一些答案也有效。我选择它是因为它最简单,我稍微修改了一下。
以下是基于答案的解决方案。
runs = [something, something1, something2]
for func in runs:
    try:
        func()
    except Keyerror as e:
        print e
6个回答

11

假设您将事物包裹在函数中,您可以尝试这样做:

for func in (something, something1, something2):
    try:
        func()
    except Keyerror as e:
        print e

6

这是我在类似情况下使用过的一个上下文管理器:

from contextlib import contextmanager

@contextmanager
def ignoring(*exceptions):
    try:
        yield
    except exceptions or Exception as e:
        print e

with ignoring(KeyError):
    something()

# you can also put it on the same line if it's just one statement
with ignoring(KeyError): something1()

with ignoring(KeyError): something2()

Python 3版本可以让您参数化在异常发生时要执行的操作(这里需要使用关键字参数):

from contextlib import contextmanager

@contextmanager
def ignoring(*exceptions, action=print):
    try:
        yield
    except exceptions or Exception as e:
        callable(action) and action(e)

如果你不想使用print函数(例如想要使用名为log的日志记录器函数),或者不需要任何函数,可以传递None(因为它会检查操作是否可调用):

with ignoring(KeyError, action=log): something()

Python 2.7还可以参数化在异常发生时要执行的操作。 - orlp
按照我的写法,你需要使用关键字参数,这是我所知道的仅适用于Python 3的特性。你可以接受一个单一的 exception 参数,然后调用者会传入一个元组,如果需要多个参数的话。 - kindall
关键字参数现在已经被移植到 Python 2.7 版本。 - orlp
@nightcracker:你确定吗?我在尝试在2.7.3中使用def f(*args, x): pass时会出现“SyntaxError”。 - user2357112
我可以确认2.7版本中没有关键字参数。虽然有一个补丁,但被拒绝了。我刚在2.7.5中尝试过了。 - kindall
抱歉大家,Python 2.7 中没有关键字参数的内在支持(我在测试时不小心将 args 中的 * 省略了)。但是,仍然可以通过像这样的方式在两个版本之间实现可移植的行为:from __future__ import print_function; def ignoring(*exceptions, **kwargs): action = kwargs.get("action", print) - orlp

2
我建议使用类似以下的方式:

我会选择这样的方式:

def safe_do(*statements):
    for statement, args, kwargs in statements:
        try:
            statement(*args, **kwargs)
        except KeyError as e:
            print e

# usage:
safe_do(
        (something1, [], {}),
        (something2, [], {}),
        )

但是,如果你只期望语句中缺少一个元素,为什么不用 if 呢?

if some_key1 in some_dict1:
    something1

if some_key2 in some_dict2:
    something2

更易读且没有任何“魔法”。

1
其他可能性
def mydec(func):
  def dec():
    try:
      func()
    except KeyError as e:
      print(e)
  return dec

@mydec
def f1():
  print('a')

@mydec
def f2():
  print('b')
  raise KeyError('Test')

f1()
f2()

0
在Python3中,如果您想要输入一个带有其参数和关键字参数的函数,您可以使用以下代码:
def safe_do(**statement):
    try:
        statement['func'](*statement['args'],**statement['kwargs'])
    except Exception as e:
        print(e)
        print(statement['func'])
        print(statement['args'])
        print(statement['kwargs'])
def divide(a,b):
  print(a/b)
safe_do(func=divide,args=[1,0],kwargs={})

我的Colab笔记本中,我展示了它。

0
这要取决于您是否在执行类似的任务或非常不同的任务。例如,如果您的something行非常相似,则可以执行以下操作:
def something(my_dict):
    try:
        d = my_dict['important_key']  # Just an example, since we
        return d                      # don't know what you're really doing
    except KeyError as e:
        print e

something(dict1)
something(dict2)
something(dict3)

然而,如果你的任务差异很大,这种方法可能不适用。在某种程度上,你正在问“如何编写高效的代码”,而答案取决于你正在编写什么样的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接