python查看所有异常,如何列出函数在Python 3中可能引发的所有异常?

本文探讨了如何在Python中准确识别和处理函数间的异常传播,重点讲解了os.makedirs和自定义异常的例子,并介绍了如何使用ast和inspect模块来分析函数的潜在异常。通过实例和代码,揭示了获取可能异常的挑战和解决策略。
摘要由CSDN通过智能技术生成

小编典典

对于某些(如果不是大多数)功能,您将无法获得可靠的结果。一些例子:

执行任意代码的函数(例如,exec(')(rorrEeulaV esiar'[::-1])引发ValueError)

不是用Python编写的函数

调用其他可以将错误传播到调用方的函数的函数

函数重新引发except:块中的活动异常

不幸的是,这个清单是不完整的。

例如os.makedirs,用Python编写,您可以查看其源代码:

...

try:

mkdir(name, mode)

except OSError as e:

if not exist_ok or e.errno != errno.EEXIST or not path.isdir(name):

raise

Bareraise重新引发最后一个活动异常(OSError或其子类之一)。这是以下类的类层次结构OSError:

+-- OSError

| +-- BlockingIOError

| +-- ChildProcessError

| +-- ConnectionError

| | +-- BrokenPipeError

| | +-- ConnectionAbortedError

| | +-- ConnectionRefusedError

| | +-- ConnectionResetError

| +-- FileExistsError

| +-- FileNotFoundError

| +-- InterruptedError

| +-- IsADirectoryError

| +-- NotADirectoryError

| +-- PermissionError

| +-- ProcessLookupError

| +-- TimeoutError

要获取确切的异常类型,您需要查看mkdir,它调用的函数,那些函数调用的函数等。

因此, 在不运行功能的情况下获取可能的异常 非常 困难,您实际上不应该这样做。

但是对于简单的情况,例如

raise Exception # without arguments

raise Exception('abc') # with arguments

组合ast模块的功能和inspect.getclosurevars(得到的异常类,在Python

3.3中引入),可以产生非常准确的结果:

from inspect import getclosurevars, getsource

from collections import ChainMap

from textwrap import dedent

import ast, os

class MyException(Exception):

pass

def g():

raise Exception

class A():

def method():

raise OSError

def f(x):

int()

A.method()

os.makedirs()

g()

raise MyException

raise ValueError('argument')

def get_exceptions(func, ids=set()):

try:

vars = ChainMap(*getclosurevars(func)[:3])

source = dedent(getsource(func))

except TypeError:

return

class _visitor(ast.NodeTransformer):

def __init__(self):

self.nodes = []

self.other = []

def visit_Raise(self, n):

self.nodes.append(n.exc)

def visit_Expr(self, n):

if not isinstance(n.value, ast.Call):

return

c, ob = n.value.func, None

if isinstance(c, ast.Attribute):

parts = []

while getattr(c, 'value', None):

parts.append(c.attr)

c = c.value

if c.id in vars:

ob = vars[c.id]

for name in reversed(parts):

ob = getattr(ob, name)

elif isinstance(c, ast.Name):

if c.id in vars:

ob = vars[c.id]

if ob is not None and id(ob) not in ids:

self.other.append(ob)

ids.add(id(ob))

v = _visitor()

v.visit(ast.parse(source))

for n in v.nodes:

if isinstance(n, (ast.Call, ast.Name)):

name = n.id if isinstance(n, ast.Name) else n.func.id

if name in vars:

yield vars[name]

for o in v.other:

yield from get_exceptions(o)

for e in get_exceptions(f):

print(e)

版画

请记住,此代码仅适用于用Python编写的函数。

2021-01-20

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值