Python:在一行中尝试语句

Bra*_*ant 67 python lines-of-code exception

在python中有一种方法可以将try/except转换为单行吗?

就像是...

b = 'some variable'
a = c | b #try statement goes here
Run Code Online (Sandbox Code Playgroud)

b声明的变量在哪里而c不是......所以c会抛出一个错误并且a会变成b......

Wal*_*ndt 70

这非常hackish,但是当我想编写一系列调试操作时,我已经在提示符下使用它:

exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,我并没有受到无单线试试除外限制的困扰,但是当我只是在尝试时,我希望readline在交互式解释器中同时回忆一大堆代码所以我可以以某种方式调整它,这个小技巧派上用场.

对于你想要完成的实际目的,你可能会尝试locals().get('c', b); 理想情况下,最好使用真正的字典而不是本地上下文,或者在运行可能或不可能设置之前将c分配给None.

  • 嘿,这回答了这个问题!:) (22认同)
  • 喜欢这个答案,超级凌乱,但有一条线,就像我喜欢的那样. (4认同)
  • Exec是代码气味,应该避免,除非没有其他工作.如果一个行代码如此重要,那么这将起作用,但你需要问问自己为什么一行如此重要. (4认同)
  • 显然不是用于生产用途,而是用于尴尬的调试会话所需要的. (3认同)

Mik*_*ham 50

没有办法在Python中将try/ exceptblock 压缩到一行.

另外,不知道Python中是否存在变量是一件坏事,就像在其他动态语言中一样.更安全的方式(和流行的风格)是将所有变量设置为某种东西.如果他们可能就不会置,将它们设置为None第一(或0''或如果它是更适用的东西.)


如果您确实首先分配了您感兴趣的所有名称,那么您确实有选项.

  • @Brant,为什么你不能抓住这个错误?为什么一行? (2认同)
  • 如果您不想要例外,请不要使用`get`.请改用"filter". (2认同)

dse*_*t0x 14

在python3中,您可以使用contextlib.suppress

from contextlib import suppress

d = {}
with suppress(KeyError): d['foo']
Run Code Online (Sandbox Code Playgroud)

  • 这应该是标准答案 (13认同)
  • 这个答案不能解决问题。`suppress` 只是在 ` except:` 上执行 `pass`,这里没有办法处理异常 (6认同)
  • @alper因为`BaseException`还处理`KeyboardInterrupt`和`SystemExit`(使用`sys.exit()`时调用的异常)等。处理这些异常将使您无法退出程序,除非您使用任务管理器或类似的强制杀死它。这是一个很好解释的视频:https://www.youtube.com/watch?v=zrVfY9SuO64 (3认同)
  • 我们可以在不给出任何异常类型(如“KeyError”)的情况下使用抑制并将其应用于所有异常吗? (2认同)
  • @alper是的,如果你想捕获像“KeyError”和“IndexError”这样的通用异常,只需使用“Exception”,但如果你想捕获“SystemExit”、“KeyboardInterrupt”和“GeneratorExit”(你也可以使用“BaseException”)大多不关心) (2认同)

Pav*_*kov 14

poke53280 版本的答案有限,预期例外。

def try_or(func, default=None, expected_exc=(Exception,)):
    try:
        return func()
    except expected_exc:
        return default
Run Code Online (Sandbox Code Playgroud)

它可以用作

In [2]: try_or(lambda: 1/2, default=float('nan'))
Out[2]: 0.5

In [3]: try_or(lambda: 1/0, default=float('nan'), expected_exc=(ArithmeticError,))
Out[3]: nan

In [4]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError,))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
[your traceback here]
TypeError: unsupported operand type(s) for /: 'str' and 'int'

In [5]: try_or(lambda: "1"/0, default=float('nan'), expected_exc=(ArithmeticError, TypeError))
Out[5]: nan
Run Code Online (Sandbox Code Playgroud)

  • @ibilgen 逗号将表达式转换为 [tuple](https://docs.python.org/3/tutorial/datastructs.html#tuples-and-sequences)。写“(Exception)”相当于省略括号。`(Exception, )` 告诉解释器这是一个只有一个条目的元组(类似于列表)。在此示例中使用了这一点,因此“expected_exc”可以是多个异常。 (2认同)

小智 12

另一种方法是定义上下文管理器:

class trialContextManager:
    def __enter__(self): pass
    def __exit__(self, *args): return True
trial = trialContextManager()
Run Code Online (Sandbox Code Playgroud)

然后使用该with语句忽略一行中的错误:

>>> with trial: a = 5      # will be executed normally
>>> with trial: a = 1 / 0  # will be not executed and no exception is raised
>>> print a
5
Run Code Online (Sandbox Code Playgroud)

在运行时错误的情况下不会引发异常.这就像try:没有了except:.

  • 这很棒!由于没有明确的 try/ except,您能否简要解释一下上下文管理器如何处理错误? (3认同)

Pun*_*rud 9

适用于 Python3,灵感来自 Walter Mundt

exec("try:some_problematic_thing()\nexcept:pass")
Run Code Online (Sandbox Code Playgroud)

将多行合并为一行

exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")
Run Code Online (Sandbox Code Playgroud)

Ps:Exec 对于您无法控制的数据使用是不安全的。


小智 7

问题是它实际上是我正在尝试测试的 django model.objects.get 查询。如果没有找到数据, .get 返回一个错误......它不返回 None (这让我很恼火)

使用这样的东西:

print("result:", try_or(lambda: model.objects.get(), '<n/a>'))
Run Code Online (Sandbox Code Playgroud)

其中 try_or 是您定义的实用程序函数:

def try_or(fn, default):
    try:
        return fn()
    except:
        return default
Run Code Online (Sandbox Code Playgroud)

您也可以选择限制接受的异常类型NameErrorAttributeError等等。

  • 有趣又好的方法!建议:“lambda”毫无意义,只需传递“model.objects.get”(没有执行调用的“()”),它就会按预期工作 (2认同)

小智 7

parse_float = lambda x, y=exec("def f(s):\n try:\n  return float(s)\n except:  return None"): f(x)
Run Code Online (Sandbox Code Playgroud)

总有解决方案。


小智 7

使用两条线怎么样。可以吗?

>>> try: a = 3; b= 0; c = a / b
... except : print('not possible'); print('zero division error')
...
not possible
zero division error
Run Code Online (Sandbox Code Playgroud)


jcd*_*yer 5

您可以通过使用vars()locals()或访问命名空间字典来完成此操作globals(),以最适合您的情况为准。

>>> b = 'some variable'
>>> a = vars().get('c', b)
Run Code Online (Sandbox Code Playgroud)

  • 这与检查变量是否已设置的工作方式并不完全相同(尽管如果您对特定范围感兴趣,它会这样做。)此外,ewwwwwwww..... (4认同)