<p>我在一个项目中工作,我们想验证一个参数是否可以在必要时作为异常引发。我们进行了以下操作:</p>
<pre><code>def is_raisable(exception):
funcs = (isinstance, issubclass)
return any(f(exception, BaseException) for f in funcs)
</code></pre>
<p>这将处理以下满足我们需求的用例(目前):</p>
^{pr2}$
<p>但是,对于旧样式的类,它失败了,因为旧版本(2.x)中可以对其进行提升。我们试着用这种方法解决这个问题:</p>
^{3}$
<p>这通过了我们所有的测试,但是它不是很漂亮,而且如果我们考虑一些我们不希望用户通过的东西,但是可能会因为其他原因被扔进去,那么它仍然会让人觉得很不舒服。在</p>
<pre><code>def test_is_raisable_exception(self):
"""Test that an exception is raisable."""
self.assertTrue(is_raisable(Exception))
def test_is_raisable_instance(self):
"""Test that an instance of an exception is raisable."""
self.assertTrue(is_raisable(Exception()))
def test_is_raisable_old_style_class(self):
"""Test that an old style class is raisable."""
class A: pass
self.assertTrue(is_raisable(A))
def test_is_raisable_old_style_class_instance(self):
"""Test that an old style class instance is raisable."""
class A: pass
self.assertTrue(is_raisable(A()))
def test_is_raisable_excluded_type_background(self):
"""Test that an exception we want to ignore isn't caught."""
class BadCustomException:
def __init__(self):
raise KeyboardInterrupt
self.assertRaises(KeyboardInterrupt, is_raisable, BadCustomException)
def test_is_raisable_excluded_type_we_want(self):
"""Test that an exception we normally want to ignore can be not
ignored."""
class BadCustomException:
def __init__(self):
raise KeyboardInterrupt
self.assertTrue(is_raisable(BadCustomException, exceptions_to_exclude=()))
def test_is_raisable_not_raisable(self):
"""Test that something not raisable isn't considered rasiable."""
self.assertFalse(is_raisable("test"))
</code></pre>
<p>不幸的是,我们需要继续支持Python2.6+(很快就只支持Python2.7,所以如果你有一个在2.6中不起作用的解决方案,那很好,但并不理想)和Python3.x。理想的情况下,我希望在没有显式测试版本的情况下这样做,但是如果没有其他方法,那就没问题了。在</p>
<p>最后,我的问题是:</p>
<ol>
<li>有没有更简单的方法来支持所有列出的版本?在</li>
<li>如果不是,是否有更好或更安全的方法来处理“特殊异常”,例如<code>KeyboardInterrupt</code>。在</li>
<li>作为最具Python的人,我想请求原谅而不是允许,但是考虑到我们可以得到两种类型的<code>TypeError</code>(一种是因为它有效,另一种是因为它不起作用),这也让人觉得奇怪(但无论如何,我还是得依靠它来获得2.x的支持)。在</li>
</ol>