【问题标题】:Does Python allow to parse a module and return all the functions/classes in it?Python 是否允许解析模块并返回其中的所有函数/类?
【发布时间】:2015-06-11 18:58:37
【问题描述】:

我很好奇,除了将 py 文件解析为文本文件之外,是否有其他方法可以检索模块内部的实际内容。

例如;如果我导入一个模块,并想知道模块包含什么,以及它的用法(需要的参数、返回类型等),有没有办法直接通过 Python 执行此操作,或者我必须实际加载文件,例如我会做一个文本文件,然后手动解析它?

我有很多要记录的模块,这样可以节省我浏览每个模块并一一检查的时间。

【问题讨论】:

标签: python


【解决方案1】:

您可以使用 ast 正确解析所有模块:

import inspect
import importlib
import ast


class ParseMod(ast.NodeVisitor):
    def visit_FuncDef(self,node):
        print("In func")
        print(node.name)
        print(node.args)
        self.generic_visit(node)

    def visit_ClassDef(self,node):
        print("in class")
        print(node.name)
        for n in node.body:
            print(n.name)
        self.generic_visit(node)

    def visit_Call(self, node):
        print("In call")
        print(node.func.id)
        print([ast.literal_eval(arg) for arg in node.args])
        self.generic_visit(node)


mod = "test2"
mod = importlib.import_module(mod)
p = ast.parse(inspect.getsource(mod))

par = ParseMod()

par.visit(p)

输入:

class Foobar(object):
    def func(self):
        return "func"


class Bar(object):
    def func2(self):
        return  "func2"

class Foo():
    def __init__(self):
        self.x = 1
        self.y = 2
        self.z = 3
    def func_foo(self):
        return "func_foo"


def some_func(a,b):
    """
    :param a: int
    :param b: int
    :return: int
    """
    return a,b

some_func(1,2)

输出:

in class
Foobar
func
in class
Bar
func2
in class
Foo
__init__
func_foo
In call
some_func
[1, 2]

greentreesnakes 文档中有所有可用属性的完整列表和每个属性的说明。

如果你只是想收集函数和类节点:

import inspect
import importlib
import ast
mod = "test"
mod = importlib.import_module(mod)
p = ast.parse(inspect.getsource(mod))



classes = [node for node in p.body if isinstance(node, ast.ClassDef)]
funcs = [node for node in p.body if isinstance(node, ast.FunctionDef)]

print(classes)
print(funcs)
[<_ast.ClassDef object at 0x7f9bc7884190>, <_ast.ClassDef object at 0x7f9bc7884350>, <_ast.ClassDef object at 0x7f9bc7884510>]    
[<_ast.FunctionDef object at 0x7f89d3377c50>]

然后从每个中提取你想要的:

for f in funcs:
    print(f.name)
    print([a.id for a in  f.args.args])
    print(ast.get_docstring(f))

some_func
['a', 'b']
:param a: int
:param b: int
:return: int

还有几个示例用法 herehere

【讨论】:

  • 非常感谢帕德莱克!这个很有用
  • @newbiez,不用担心,很难提供更完整的示例,因为获取数据的方法有无数种,但 ast 在处理源代码时是一个非常强大的工具。我将添加一些指向我的其他答案的链接,以获得各种输出
  • 确实;你付出了额外的努力来展示这个概念,我很感激,因为我是 Python 的初学者。谢谢!
  • @newbiez,没问题,我使用 ast 为不同目的添加了几个答案链接
【解决方案2】:

您可以使用dir 方法获取与模块的每个成员对应的字符串列表:

import some_module
print dir(some_module)

这将为您提供模块的所有类和功能,但有两个缺点:

  • 为您提供不是类或函数的成员。例如,dir(Tkinter) 包含 VERTICALSUNKENOFFINSERT,它们都是普通字符串。
  • 如果模块包含文件级别的任何代码,则将执行该代码。通常没什么大不了的,但如果您要检查大量模块,则浪费的时间可能会越来越多。

【讨论】:

  • 坦克凯文;这两个问题可能很麻烦;到目前为止,我尝试的几个模块都返回了我需要的东西,但我需要更多时间来调查
【解决方案3】:

一种方法是使用inspect.getmembers() 内省模块的内容:

import types
import inspect
import mymodule

# find classes, shove them in a {'name':object} dict
is_class = lambda x: isinstance(x, type)
classes = dict(inspect.getmembers(mymodule, predicate=is_class))

# find functions, shove them in a {'name':object} dict
is_func = lambda x: isinstance(x, (types.FunctionType, types.BuiltinFunctionType))
functions = dict(inspect.getmembers(mymodule, predicate=is_func))

# etc...

听起来您真正想要的是一个自动生成 API 文档的工具,of which there are several

【讨论】:

  • 感谢阿里;文档自动化是目的之一;我也很想知道如何在 python 模块中进行自省。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 2020-11-19
  • 2011-10-25
  • 2021-08-31
相关资源
最近更新 更多