首先让我说:这将用于深奥的目的 - 而不是生产代码。我正在尝试在一行 Python 代码中做一些事情,因此我需要表达式而不是语句。 (编辑:我正在努力将代码机械地编译成单行(大部分)等效的 Python 代码,BitBucket - onelinepython。请注意,它正在进行中,因此我在最初提到它时保持沉默)
我基本上想做两件事:
调用一个引发我选择的异常实例的函数,例如:
raise_exception(WhateverException())
在一个封闭的环境中运行一个函数,在这里我可以获得引发的异常实例(如果引发异常),否则,我可以获取被调用函数的返回值。例如:
has_exception, return_or_exception = check_exception(f, param1, param2, ...)
理想情况下,我想使用一些默认库或内置函数来执行此操作(无论我必须对其预期用途进行多少破坏)。我不需要与我提供的示例具有完全相同签名的函数,只是一些我可以分解成足够接近的东西。不过,我确实有一个限制:不使用 eval() 或等效函数。
编辑: 我知道我可以定义自己的函数来执行此操作,但是它们仍然必须遵循它们是单个表达式的限制。因此,在函数定义中使用 raise
和 try
的解决方案已经过时了。不幸的是,函数定义、raise 语句和 try block 是语句而不是表达式。
至于我尝试过的任何解决方案。答案是还没有。关于如何解决这个问题,我最接近的想法是滥用 unittest
的断言功能,但我认为这是死胡同。
编辑 2: 为了清楚起见,我可以使用模块或使用 raise
-statements 或 try
- 的模块在其代码中的某处阻塞。我的目标是获取一些代码并将其转换为等效的单行代码(其中包括我可能使用的任何辅助函数)。但是因为我希望它在默认安装的 Python 上工作,所以我只想使用默认库。
最佳答案
引发异常:
>>> import warnings
>>> WV = type("WV", (Warning, ValueError), {})
>>> warnings.simplefilter("error", WV)
>>> warnings.warn("wv", WV)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.WV: wv
捕获异常:
>>> import unittest
>>> res = type("TR", (unittest.TestResult, ), dict(addError=lambda self, test, err: setattr(self, '_last_err', err)))()
>>> unittest.FunctionTestCase(lambda: [][0])(res)
>>> res._last_err
(<type 'exceptions.IndexError'>, IndexError('list index out of range',), <traceback object at 0x2b4358e69950>)
请注意,warnings
方法仅适用于派生自 Warning
的异常,但您应该始终能够进行多重继承;这是一个例子:
>>> WS = type("WS", (Warning, StopIteration), {})
>>> warnings.simplefilter("error", WS)
>>> list(type("R", (object,), dict(__init__=lambda self, stop: (setattr(self, 'stop', stop), setattr(self, 'i', 0), None)[-1], __iter__=lambda self: self, next=lambda self: (self.i, setattr(self, 'i', self.i + 1))[0] if self.i < self.stop else warnings.warn("Stop", WS)))(5))
[0, 1, 2, 3, 4]
关于python - 在 Python 3 的表达式中引发和捕获异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11089808/