Python:在一行中尝试语句

时间:2010-03-26 16:21:19

标签: python exception-handling

python中是否有办法将try / except转为一行?

类似......

b = 'some variable'
a = c | b #try statement goes here

b是声明的变量而c不是......所以c会抛出错误而a会变成b ...

14 个答案:

答案 0 :(得分:65)

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

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

在大多数情况下,我完全没有受到单行 - 尝试 - 除外限制的困扰,但是当我只是尝试并且我想让readline回想起整个代码块时在交互式翻译中,我可以在某种程度上调整它,这个小技巧就派上用场了。

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

答案 1 :(得分:44)

无法在Python中将try / except块压缩到一行。

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


如果您执行首先分配您感兴趣的所有名称,您可以选择。

  • 最佳选择是if语句。

    c = None
    b = [1, 2]
    
    if c is None:
        a = b
    else:
        a = c
    
  • 单行选项是条件表达式。

    c = None
    b = [1, 2]
    a = c if c is not None else b
    
  • 有些人滥用or的短路行为来做这件事。 这很容易出错,所以我从不使用它。

    c = None
    b = [1, 2]
    a = c or b
    

    考虑以下情况:

    c = []
    b = [1, 2]
    a = c or b
    

    在这种情况下,a可能应该[],但它是[1, 2],因为[]在布尔上下文中为false。因为有很多值可能是错误的,所以我不使用or技巧。 (这是人们在if foo:表示if foo is not None:时会遇到同样的问题。)

答案 2 :(得分:9)

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

class trialContextManager:
    def __enter__(self): pass
    def __exit__(self, *args): return True
trial = trialContextManager()

然后使用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

如果出现运行时错误,则不会引发异常。它就像没有try:的{​​{1}}。

答案 3 :(得分:5)

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

始终有解决方案。

答案 4 :(得分:5)

如何使用两行。可以吗?

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

答案 5 :(得分:4)

您可以使用vars()locals()globals()访问命名空间字典,以最适合您的情况为准。

>>> b = 'some variable'
>>> a = vars().get('c', b)

答案 6 :(得分:2)

你提到你正在使用django。如果您正在做的事情有意义,您可能想要使用:

my_instance, created = MyModel.objects.get_or_create()

created将为真或假。也许这会对你有帮助。

答案 7 :(得分:2)

  

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

使用类似的东西:

print("result:", try_or(lambda: model.objects.get(), '<n/a>'))

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

def try_or(fn, default):
    try:
        return fn()
    except:
        return default

您可以选择将接受的例外类型限制为NameErrorAttributeError等。

答案 8 :(得分:2)

受Walter Mundt启发,在Python3上工作

for event in pygame.event.get():

        # Always here to make it possible to exit when pressing X in game window:
        if event.type == pygame.QUIT:
                self.playing = False
                pygame.quit()
                quit()

        # Left mouse button down events:
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            pos = pygame.mouse.get_pos()
                    if button.collidepoint(pos):
                        print('do what button is supposed to do')

将多行合并为一行

exec("try:some_problematic_thing()\nexcept:pass")

Ps:Exec不安全地用于无法控制的数据。

答案 9 :(得分:1)

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

from contextlib import suppress

d = {}
with suppress(KeyError): d['foo']

答案 10 :(得分:1)

在一行中使用 with 语法:

class OK(): __init__ = lambda self, *isok: setattr(self, 'isok', isok); __enter__ = lambda self: None; __exit__ = lambda self, exc_type, exc_value, traceback: (True if not self.isok or issubclass(exc_type, self.isok) else None) if exc_type else None

忽略任何错误:

with OK(): 1/0

忽略指定的错误:

with OK(ZeroDivisionError, NameError): 1/0

答案 11 :(得分:0)

如果您需要实际管理例外:
(修改自poke53280的回答)

>>> def try_or(fn, exceptions: dict = {}):
    try:
        return fn()
    except Exception as ei:
        for e in ei.__class__.__mro__[:-1]:
            if e in exceptions: return exceptions[e]()
        else:
            raise


>>> def context():
    return 1 + None

>>> try_or( context, {TypeError: lambda: print('TypeError exception')} )
TypeError exception
>>> 

请注意,如果不支持该异常,它将按预期提升:

>>> try_or( context, {ValueError: lambda: print('ValueError exception')} )
Traceback (most recent call last):
  File "<pyshell#57>", line 1, in <module>
    try_or( context, {ValueError: lambda: print('ValueError exception')} )
  File "<pyshell#38>", line 3, in try_or
    return fn()
  File "<pyshell#56>", line 2, in context
    return 1 + None
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
>>> 

如果给出Exception,它将匹配以下任何内容 (BaseException更高,因此不匹配)

>>> try_or( context, {Exception: lambda: print('exception')} )
exception

答案 12 :(得分:0)

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

def try_or(func, default=None, expected_exc=(Exception,)):
    try:
        return func()
    except expected_exc:
        return default

它可以用作

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

答案 13 :(得分:0)

这是@surendra_ben提供的答案的简单版本

a = "apple"
​
try: a.something_that_definitely_doesnt_exist
except: print("nope")

...

nope