【发布时间】:2011-02-01 06:19:18
【问题描述】:
在 python 中有没有办法将 try/except 变成单行?
类似...
b = 'some variable'
a = c | b #try statement goes here
其中b 是已声明的变量,而c 不是...所以c 会抛出错误,a 会变成b...
【问题讨论】:
标签: python exception lines-of-code
在 python 中有没有办法将 try/except 变成单行?
类似...
b = 'some variable'
a = c | b #try statement goes here
其中b 是已声明的变量,而c 不是...所以c 会抛出错误,a 会变成b...
【问题讨论】:
标签: python exception lines-of-code
两行版本对我不起作用。我在 ubuntu 20.04 x64 上使用 VSCode。它只有在我将异常语句移到新行时才有效。尝试可以保持单行。所以至少我需要3行。不知道这是bug还是功能。
【讨论】:
在一行中使用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
【讨论】:
这是@surendra_ben 提供的答案的更简单版本
a = "apple"
try: a.something_that_definitely_doesnt_exist
except: print("nope")
...
nope
【讨论】:
使用两条线怎么样。可以吗?
>>> try: a = 3; b= 0; c = a / b
... except : print('not possible'); print('zero division error')
...
not possible
zero division error
【讨论】:
在 Python3 上工作,灵感来自 Walter Mundt
exec("try:some_problematic_thing()\nexcept:pass")
多行合为一行
exec("try:\n\tprint('FirstLineOk')\n\tsome_problematic_thing()\n\tprint('ThirdLineNotTriggerd')\nexcept:pass")
Ps:Exec 在您无法控制的数据上使用是不安全的。
【讨论】:
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
【讨论】:
(Exception) 等于省略括号。 (Exception, ) 告诉解释器这是一个包含一个条目的元组(类似于列表)。在本例中使用了这个,所以expected_exc 可以是多个例外。
在python3中你可以使用contextlib.suppress:
from contextlib import suppress
d = {}
with suppress(KeyError): d['foo']
【讨论】:
suppress 只需在 except: 上执行 pass,这里没有办法处理异常
KeyError)的情况下使用抑制并将其应用于所有异常吗?
KeyError和IndexError这样的通用异常,只需使用Exception,但如果你想捕捉SystemExit,KeyboardInterrupt和BaseException GeneratorExit 也一样(你大多不关心)
BaseException 还处理KeyboardInterrupt 和SystemExit(使用sys.exit() 时调用的异常)等。处理这些异常将使您无法退出程序除非您使用任务管理器或类似工具强制杀死它。这是一个很好地解释它的视频:youtube.com/watch?v=zrVfY9SuO64
如果您需要实际管理异常:
(修改自 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
【讨论】:
parse_float = lambda x, y=exec("def f(s):\n try:\n return float(s)\n except: return None"): f(x)
总会有解决办法的。
【讨论】:
问题在于它实际上是我正在尝试测试的 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
您可以选择将接受的异常类型限制为NameError、AttributeError 等。
【讨论】:
lambda 没有意义,只需传递model.objects.get(没有执行呼叫的()),它就会按预期工作
另一种方式是定义上下文管理器:
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
如果出现运行时错误,不会引发异常。就像没有except: 的try:。
【讨论】:
在 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],因为[] 在布尔上下文中为假。因为有很多值可能是假的,所以我不使用or 技巧。 (这与人们在说if foo: 时遇到的问题相同,而他们的意思是if foo is not None:。)
【讨论】:
try/except 块没有单行语法。幸运的是线路很便宜,所以 4 线路解决方案应该适合您。 ;-)
get。请改用filter。
这非常骇人听闻,但是当我想编写一系列用于调试的操作时,我已经在提示符下使用了它:
exec "try: some_problematic_thing()\nexcept: problem=sys.exc_info()"
print "The problem is %s" % problem[1]
在大多数情况下,我根本不会被 no-single-line-try-except 限制所困扰,但是当我只是在试验并且我希望 readline 一次调用整个代码块时交互式解释器,以便我可以以某种方式对其进行调整,这个小技巧就派上用场了。
对于你想要达到的实际目的,你可以试试locals().get('c', b);理想情况下,最好使用真正的字典而不是本地上下文,或者在运行任何可能或可能不设置它之前将 c 分配给 None。
【讨论】:
problem[0] 会返回该函数返回的内容吗?
您可以通过使用vars()、locals() 或globals() 访问命名空间字典来做到这一点,以最适合您的情况为准。
>>> b = 'some variable'
>>> a = vars().get('c', b)
【讨论】:
您提到您正在使用 django。如果它对你正在做的事情有意义,你可能想要使用:
my_instance, created = MyModel.objects.get_or_create()
created 将是 True 或 False。也许这会对你有所帮助。
【讨论】: