有没有办法知道(在编码时)执行python代码时会遇到哪些异常?我最终会在90%的时间内捕获基本Exception类,因为我不知道可能抛出哪种异常类型(并且不要告诉我阅读文档.很多时候,异常可以从深层传播.文档未更新或更正的时间).有什么工具可以检查吗?(比如通过阅读python代码和库)?
P S*_*ved 24
您应该只捕获您将处理的异常.
通过具体类型捕获所有异常是无稽之谈.您应该捕获可以并且将要处理的特定异常.对于其他异常,您可以编写一个捕获"基本异常"的通用catch,记录它(使用str()
函数)并终止您的程序(或者在崩溃的情况下执行其他适当的操作).
如果您真的要处理所有异常,并且确定它们都不是致命的(例如,如果您在某种沙盒环境中运行代码),那么捕获泛型BaseException的方法符合您的目标.
您可能也对语言异常参考感兴趣,而不是您正在使用的库的参考.
如果库引用真的很差并且在捕获系统时它没有重新抛出自己的异常,唯一有用的方法是运行测试(可能将它添加到测试套件中,因为如果某些内容没有记录,它可能会改变!) .删除对您的代码至关重要的文件,并检查抛出的异常.提供过多数据并检查它产生的错误.
无论如何你都必须运行测试,因为即使存在通过源代码获取异常的方法,它也不会让你知道如何处理任何这些.也许您应该显示错误消息"找不到文件needful.txt!" 什么时候赶上IndexError
?只有测试可以告诉.
And*_*ikh 22
我想解决方案可能只是不精确,因为缺乏静态类型规则.
我不知道有一些检查异常的工具,但你可以提出自己的工具来满足你的需求(很有可能在静态分析中玩一点).
作为第一次尝试,您可以编写一个构建AST的函数,查找所有Raise
节点,然后尝试找出引发异常的常见模式(例如直接调用构造函数)
让我们x
成为以下计划:
x = '''\
if f(x):
raise IOError(errno.ENOENT, 'not found')
else:
e = g(x)
raise e
'''
Run Code Online (Sandbox Code Playgroud)
使用compiler
包构建AST :
tree = compiler.parse(x)
Run Code Online (Sandbox Code Playgroud)
然后定义一个Raise
访客类:
class RaiseVisitor(object):
def __init__(self):
self.nodes = []
def visitRaise(self, n):
self.nodes.append(n)
Run Code Online (Sandbox Code Playgroud)
并走AST收集Raise
节点:
v = RaiseVisitor()
compiler.walk(tree, v)
>>> print v.nodes
[
Raise(
CallFunc(
Name('IOError'),
[Getattr(Name('errno'), 'ENOENT'), Const('not found')],
None, None),
None, None),
Raise(Name('e'), None, None),
]
Run Code Online (Sandbox Code Playgroud)
您可以继续使用编译器符号表解析符号,分析数据依赖性等.或者您可以推断,CallFunc(Name('IOError'), ...)
"应该绝对意味着提升IOError
",这对于快速实际结果来说是相当不错的:)
Joh*_*ooy 12
解决这个问题的正确工具是单元测试.如果你有真实代码引发的异常,单元测试不会引发,那么你需要更多的单元测试.
考虑一下
def f(duck):
try:
duck.quack()
except ??? could be anything
Run Code Online (Sandbox Code Playgroud)
鸭子可以是任何物体
显然你可以有一个AttributeError
如果鸭子没有嘎嘎,TypeError
如果鸭子有一个庸医但它不可驯服.你不知道会发生什么duck.quack()
,甚至可能是DuckError
什么
现在假设你有这样的代码
arr[i] = get_something_from_database()
Run Code Online (Sandbox Code Playgroud)
如果它引发了IndexError
你不知道它是来自arr [i]还是来自数据库函数的深处.通常情况下,异常发生的地方并不重要,而是出现了问题而你想要发生的事情并没有发生.
一个方便的技术是捕获并可能像这样重新加入异常
except Exception as e
#inspect e, decide what to do
raise
Run Code Online (Sandbox Code Playgroud)
我在使用 socket 时遇到了这个问题,我想找出我会遇到的所有错误情况(因此,与其试图创建错误并找出是什么 socket,我只想要一个简洁的列表)。最终,我最终将“/usr/lib64/python2.4/test/test_socket.py”用于“raise”:
$ grep raise test_socket.py
Any exceptions raised by the clients during their tests
raise TypeError, "test_func must be a callable function"
raise NotImplementedError, "clientSetUp must be implemented."
def raise_error(*args, **kwargs):
raise socket.error
def raise_herror(*args, **kwargs):
raise socket.herror
def raise_gaierror(*args, **kwargs):
raise socket.gaierror
self.failUnlessRaises(socket.error, raise_error,
self.failUnlessRaises(socket.error, raise_herror,
self.failUnlessRaises(socket.error, raise_gaierror,
raise socket.error
# Check that setting it to an invalid value raises ValueError
# Check that setting it to an invalid type raises TypeError
def raise_timeout(*args, **kwargs):
self.failUnlessRaises(socket.timeout, raise_timeout,
def raise_timeout(*args, **kwargs):
self.failUnlessRaises(socket.timeout, raise_timeout,
Run Code Online (Sandbox Code Playgroud)
这是一个非常简洁的错误列表。当然,这仅适用于个案,并取决于测试是否准确(通常是这样)。否则,您几乎需要捕获所有异常,记录它们并剖析它们并弄清楚如何处理它们(通过单元测试不会很难)。
到目前为止,没有人解释,为什么您不能拥有完整的100%正确的例外列表,所以我认为值得一提。原因之一是一流的功能。假设您有一个像这样的函数:
def apl(f,arg):
return f(arg)
Run Code Online (Sandbox Code Playgroud)
现在apl
可以引发任何f
引发的异常。尽管在核心库中没有很多类似的功能,但是使用自定义过滤器,映射,归约等使用列表理解的任何内容都会受到影响。
文档和源代码分析器是这里唯一的“大量”信息源。只要记住他们不能做什么。