简体   繁体   English

如何查找给定库函数在Python中引发的所有异常列表?

[英]How Can I Find a List of All Exceptions That a Given Library Function Throws in Python?

Sorry for the long title, but it seems most descriptive for my question. 很抱歉这个长标题,但它似乎对我的问题最具描述性。

Basically, I'm having a difficult time finding exception information in the official python documentation. 基本上,我很难在官方python文档中找到异常信息。 For example, in one program I'm currently writing, I'm using the shutil libary's move function: 例如,在我正在编写的一个程序中,我正在使用shutil libary的move函数:

from shutil import move
move('somefile.txt', '/tmp/somefile.txt')

That works fine, as long as I have write access to /tmp/, there is enough diskspace, and if all other requirements are satisfied. 这工作正常,只要我有/ tmp /的写访问权限,就有足够的磁盘空间,并且满足所有其他要求。

However, when writing generic code, it is often difficult to guarantee those factors, so one usually uses exceptions: 但是,在编写通用代码时,通常很难保证这些因素,因此通常使用异常:

from shutil import move
try:
    move('somefile.txt', '/tmp/somefile.txt')
except:
    print 'Move failed for some reason.'

I'd like to actually catch the appropriate exceptions thrown instead of just catching everything , but I simply can't find a list of exceptions thrown for most python modules. 我想实际捕获适当的异常抛出而不是只捕获所有内容 ,但我根本找不到大多数python模块抛出的异常列表。 Is there a way for me to see which exceptions a given function can throw, and why? 有没有办法让我看看给定函数可以抛出哪些异常,为什么? This way I can make appropriate cases for each exception, eg: 这样我可以为每个例外做出适当的案例,例如:

from shutil import move
try:
    move('somefile.txt', '/tmp/somefile.txt')
except PermissionDenied:
    print 'No permission.'
except DestinationDoesNotExist:
    print "/tmp/ doesn't exist"
except NoDiskSpace:
    print 'No diskspace available.'

Answer points go to whoever can either link me to some relevant documentation that I've somehow overlooked in the official docs, or provide a sure-fire way to figure out exactly which exceptions are thrown by which functions, and why. 答案要点是谁可以将我链接到一些我在官方文档中忽略的相关文档,或者提供一种确定的方法来确定哪些函数抛出了哪些异常,以及为什么。

Thanks! 谢谢!

UPDATE : It seems from the answers given that there really isn't a 100% straight-forward way to figure out which errors are thrown by specific functions. 更新 :从给出的答案看来,确实没有100%直接的方法来确定特定功能抛出哪些错误。 With meta programming, it seems that I can figure out simple cases and list some exceptions, but this is not a particularly useful or convenient method. 使用元编程,似乎我可以找出简单的情况并列出一些例外,但这不是一个特别有用或方便的方法。

I'd like to think that eventually there will be some standard for defining which exceptions are raised by each python function, and that this information will be included in the official documentation. 我想最终会有一些标准来定义每个python函数引发的异常,并且这些信息将包含在官方文档中。 Until then I think I will just allow those exceptions to pass through and error out for my users as it seems like the most sane thing to do. 在那之前,我想我会允许这些异常通过并为我的用户输出错误,因为这似乎是最理智的事情。

To amplify Messa, catch what you expect are failure modes that you know how to recover from. 为了放大Messa,抓住你所期望的失败模式,你知道如何恢复。 Ian Bicking wrote an article that addresses some of the overarching principles as does Eli Bendersky's note . Ian Bicking写了一篇文章 ,与Eli Bendersky的笔记一样,解决了一些总体原则。

The problem with the sample code is that it is not handling errors, just prettifying them and discarding them. 示例代码的问题在于它处理错误,只是对它们进行美化并丢弃它们。 Your code does not "know" what to do with a NameError and there isn't much it should do other than pass it up, look at Bicking's re-raise if you feel you must add detail. 你的代码并不“知道”如何处理NameError,除了传递它之外没什么应该做的,如果你觉得必须添加细节,请查看Bicking的重新加注。

IOError and OSError are reasonably "expectable" for a shutil.move but not necessarily handleable. 对于shutil.move ,IOError和OSError是合理的“可预期的”但不一定可以处理。 And the caller of your function wanted it to move a file and may itself break if that "contract" that Eli writes of is broken. 你的函数的调用者希望它移动一个文件,如果Eli写的那个“契约”被破坏,它本身可能会破坏。

Catch what you can fix, adorn and re-raise what you expect but can't fix, and let the caller deal with what you didn't expect, even if the code that "deals" is seven levels up the stack in main . 抓住你可以修复,装饰和重新提升你期望但无法修复的东西,并让调用者处理你没想到的东西,即使“处理”的代码是main的堆栈中的七个级别。

Python doesn't have a mechanism right now for declaring which exceptions are thrown, unlike (for example) Java. Python现在没有一种机制来声明抛出哪些异常,这与(例如)Java不同。 (In Java you have to define exactly which exceptions are thrown by what, and if one of your utility methods needs to throw another exception then you need to add it to all of the methods which call it which gets boring quickly!) (在Java中,你必须确切地定义哪些异常被抛出,如果你的一个实用程序方法需要抛出另一个异常,那么你需要将它添加到调用它的所有方法中,这很快就会枯燥!)

So if you want to discover exactly which exceptions are thrown by any given bit of python then you need to examine the documentation and the source. 因此,如果您想要确切地发现任何给定的python位引发了哪些异常,那么您需要检查文档和源代码。

However python has a really good exception hierarchy. 但是python有一个非常好的异常层次结构。

If you study the exception hierarchy below you'll see that the error superclass you want to catch is called StandardError - this should catch all the errors that might be generated in normal operations. 如果您研究下面的异常层次结构,您将看到要捕获的错误超类称为StandardError - 这应该捕获在正常操作中可能生成的所有错误。 Turning the error into into a string will give a reasonable idea to the user as to what went wrong, so I'd suggest your code above should look like 将错误转换为字符串将为用户提供关于出错的合理建议,因此我建议您的上面的代码应该看起来像

from shutil import move
try:
    move('somefile.txt', '/tmp/somefile.txt')
except StandardError, e:
    print 'Move failed: %s' % e

Exception hierarchy 异常层次结构

BaseException
|---Exception
|---|---StandardError
|---|---|---ArithmeticError
|---|---|---|---FloatingPointError
|---|---|---|---OverflowError
|---|---|---|---ZeroDivisionError
|---|---|---AssertionError
|---|---|---AttributeError
|---|---|---BufferError
|---|---|---EOFError
|---|---|---EnvironmentError
|---|---|---|---IOError
|---|---|---|---OSError
|---|---|---ImportError
|---|---|---LookupError
|---|---|---|---IndexError
|---|---|---|---KeyError
|---|---|---MemoryError
|---|---|---NameError
|---|---|---|---UnboundLocalError
|---|---|---ReferenceError
|---|---|---RuntimeError
|---|---|---|---NotImplementedError
|---|---|---SyntaxError
|---|---|---|---IndentationError
|---|---|---|---|---TabError
|---|---|---SystemError
|---|---|---TypeError
|---|---|---ValueError
|---|---|---|---UnicodeError
|---|---|---|---|---UnicodeDecodeError
|---|---|---|---|---UnicodeEncodeError
|---|---|---|---|---UnicodeTranslateError
|---|---StopIteration
|---|---Warning
|---|---|---BytesWarning
|---|---|---DeprecationWarning
|---|---|---FutureWarning
|---|---|---ImportWarning
|---|---|---PendingDeprecationWarning
|---|---|---RuntimeWarning
|---|---|---SyntaxWarning
|---|---|---UnicodeWarning
|---|---|---UserWarning
|---GeneratorExit
|---KeyboardInterrupt
|---SystemExit

This also means that when defining your own exceptions you should base them off StandardError not Exception. 这也意味着在定义自己的异常时,应该将它们基于StandardError而不是Exception。

Base class for all standard Python exceptions that do not represent
interpreter exiting.

Yes, you can (for simple cases), but you need a bit of meta-programming. 是的,你可以(对于简单的情况),但你需要一些元编程。 Like the other answers have said, a function does not declare that it throws a particular error type, so you need to look at the module and see what exception types it defines, or what exception types it raises. 与其他答案一样,函数不会声明它会抛出特定的错误类型,因此您需要查看模块并查看它定义的异常类型或它引发的异常类型。 You can either try to grok the documentation or leverage the Python API to do this. 您可以尝试浏览文档或利用Python API执行此操作。

To first find which exception types a module defines, just write a simple script to go through each object in the module dictionary module.__dict__ and see if it ends in the word "Error" or if it is a subclass of Exception: 要首先找到模块定义的异常类型,只需编写一个简单的脚本来遍历模块字典module.__dict__中的每个对象module.__dict__并查看它是否以单词“Error”结尾,或者它是否是Exception的子类:

def listexns(mod):
    """Saved as: http://gist.github.com/402861
    """
    module = __import__(mod)
    exns = []
    for name in module.__dict__:
        if (issubclass(module.__dict__[name], Exception) or
            name.endswith('Error')):
            exns.append(name)
    for name in exns:
        print '%s.%s is an exception type' % (str(mod), name)
    return

If I run this on your example of shutils I get this: 如果我在你的shutils例子上运行这个我得到这个:

$ python listexn.py shutil
Looking for exception types in module: shutil
shutil.Error is an exception type
shutil.WindowsError is an exception type
$

That tells you which error types are defined, but not which ones are thrown. 这告诉您定义了哪些错误类型,但不会抛出哪些错误类型。 To achieve the latter, we need to walk over the abstract syntax tree generated when the Python interpreter parses the module, and look for every raise statement, then save a list of names which are raised. 为了实现后者,我们需要遍历Python解释器解析模块时生成的抽象语法树,并查找每个raise语句,然后保存引发的名称列表。 The code for this is a little long, so first I'll state the output: 这个代码有点长,所以首先我要说明输出:

$ python listexn-raised.py /usr/lib/python2.6/shutil.py
Looking for exception types in: /usr/lib/python2.6/shutil.py
/usr/lib/python2.6/shutil.py:OSError is an exception type
/usr/lib/python2.6/shutil.py:Error is an exception type
$ 

So, now we know that shutil.py defines the error types Error and WindowsError and raises the exception types OSError and Error . 所以,现在我们知道shutil.py定义错误类型ErrorWindowsError并引发异常类型OSErrorError If we want to be a bit more complete, we could write another method to check every except clause to also see which exceptions shutil handles. 如果我们想要更完整,我们可以编写另一个方法来检查每个except子句,以查看shutil处理的异常。

Here's the code to walk over the AST, it just uses the compiler.visitor interface to create a walker which implements the "visitor pattern" from the Gang of Four book: 这是遍历AST的代码,它只是使用compiler.visitor接口来创建一个walker,它实现了Gang of Four书中的“访问者模式”:

class ExceptionFinder(visitor.ASTVisitor):
    """List all exceptions raised by a module. 
    Saved as: http://gist.github.com/402869
    """

    def __init__(self, filename):
        visitor.ASTVisitor.__init__(self)
        self.filename = filename
        self.exns = set()
        return

    def __visitName(self, node):
        """Should not be called by generic visit, otherwise every name
        will be reported as an exception type.
        """
        self.exns.add(node.name)
        return

    def __visitCallFunc(self, node):
        """Should not be called by generic visit, otherwise every name
        will be reported as an exception type.
        """
        self.__visitName(node.node)
        return

    def visitRaise(self, node):
        """Visit a raise statement.
        Cheat the default dispatcher.
        """
        if issubclass(node.expr1, compiler.ast.Name):
            self.__visitName(node.expr1)
        elif isinstance(node.expr1, compiler.ast.CallFunc):
            self.__visitCallFunc(node.expr1)
        return

As these operations usually use libc functions and operating system calls, mostly you get IOError or OSError with an errno number; 由于这些操作通常使用libc函数和操作系统调用,因此大多数情况下会得到带有错误号的IOError或OSError; these errors are listed in man pages of that libc/OS calls. 这些错误列在该libc / OS调用的手册页中。

I know this is possibly not a complete answer, it would be good to have all exceptions listed in documentation... 我知道这可能不是一个完整的答案,最好在文档中列出所有例外情况......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何查找列表中是否有函数(Python) - How can I find if a function is in the list (Python) 如何用 python 中的 *args 减去 function 中的所有给定数字? - How can I subtract all given numbers in function with *args in python? 在哪里可以找到Python可能的异常列表? - Where can I find a list of possible exceptions in Python? 如何列出函数可以在Python 3中引发的所有异常? - How to list all exceptions a function could raise in Python 3? 如何找到列表列表的所有可能组合(在Python中)? - How can I find all the possible combinations of a list of lists (in Python)? 如何在给定数字列表的情况下查找加法的所有变体-Python - How to find all variations of addition given a list of numbers - Python 如何在给定的矩形列表中找到与特定矩形相邻的所有矩形? - How can I find all rectangles adjacent to particular rectangle on a given list of rectangles? 如何在给定值的 n 分钟内找到列表中的所有日期时间? - How can I find all datetimes in a list within n minutes of a given value? 如何找到 python 库路径? - How can I find python library path? Python:如何找到与给定的多种模式匹配的所有字符串 - Python: How can I find all strings matching any of the multiple patterns given
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM