让Python的`assert`抛出我选择的异常
我可以让 assert
抛出我选择的异常而不是 AssertionError
吗?
更新:
我将解释我的动机:到目前为止,我已经进行了断言式测试,这些测试引发了我自己的异常;例如,当您使用某些参数创建 Node
对象时,它会检查这些参数是否适合创建节点,如果不适合,则会引发 NodeError
。
但我知道 Python 有一个 -o
模式,在该模式下断言会被跳过,我希望能够使用它,因为它会让我的程序更快。但我仍然希望有自己的例外。这就是为什么我想在我自己的异常中使用断言。
Can I make assert
throw an exception that I choose instead of AssertionError
?
UPDATE:
I'll explain my motivation: Up to now, I've had assertion-style tests that raised my own exceptions; For example, when you created a Node
object with certain arguments, it would check if the arguments were good for creating a node, and if not it would raise NodeError
.
But I know that Python has a -o
mode in which asserts are skipped, which I would like to have available because it would make my program faster. But I would still like to have my own exceptions. That's why I want to use assert with my own exceptions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这会起作用。但这有点疯狂。
为什么不是下面的呢?这不那么疯狂。
它只比
assert
语句稍微冗长一些,但并不违反我们的预期,即断言失败会引发AssertionError
。考虑一下这一点。
然后你或多或少可以用这样的东西替换你现有的断言。
完成此操作后,您现在可以自由地启用或禁用或任何您想要执行的操作。
另外,请阅读 警告 模块。这可能正是您想要做的。
This will work. But it's kind of crazy.
Why not the following? This is less crazy.
It's only a little wordier than the
assert
statement, but doesn't violate our expectation that assert failures raiseAssertionError
.Consider this.
Then you can more-or-less replace your existing assertions with something like this.
Once you've done this, you are now free to fuss around with enable or disabling or whatever it is you're trying to do.
Also, read up on the warnings module. This may be exactly what you're trying to do.
这个怎么样?
How about this?
切勿将断言用于逻辑!仅用于可选测试检查。请记住,如果 Python 在打开优化的情况下运行,则断言甚至不会编译到字节码中。如果你这样做,你显然关心引发的异常,如果你关心,那么你首先就使用了错误的断言。
Never use an assertion for logic! Only for optional testing checks. Remember, if Python is running with optimizations turned on, asserts aren't even compiled into the bytecode. If you're doing this, you obviously care about the exception being raised and if you care, then you're using asserts wrong in the first place.
当使用
-o
选项运行时,Python 也会跳过if __debug__:
块。下面的代码比较冗长,但无需黑客即可完成您需要的操作:您可以通过在
my_assert()
内移动if __debug__:
条件来缩短代码,但随后它会启用优化时调用(内部没有任何操作)。Python also skips
if __debug__:
blocks when run with-o
option. The following code is more verbose, but does what you need without hacks:You can make it shorter by moving
if __debug__:
condition insidemy_assert()
, but then it will be called (without any action inside) when optimization is enabled.您可以让 上下文管理器 在 with 中为您进行转换块(可能包含多个断言,或者更多代码和函数调用或您想要的内容。
请参阅此答案的先前版本以直接替换构造的异常对象(
KeyError("bad key")
) ,而不是重用断言的参数。You can let a context manager do the conversion for you, inside a with block (which may contain more than one assertion, or more code and function calls or what you want.
See a previous version of this answer for substituting constructed exception objects directly (
KeyError("bad key")
), instead of reusing the assertions' argument(s).至少在 Python 2.6.3 中,这也可以工作:
In Python 2.6.3 at least, this will also work:
如果你想为此使用断言,这似乎工作得很好:
请注意,在断言中,只有在条件为 false 时才会评估逗号后面的内容,因此
ValueError
只会是在需要时创建并提出。If you want to use asserts for this, this seems to work pretty well:
Note that in the assert, the stuff after the comma will only be evaluated if the condition is false, so the
ValueError
will only be created and raised when needed.为了看看尝试是否有任何开销,我
在这里尝试了这个实验是 myassert.py
To see if try has any overhead I tried this experiment
here is myassert.py