gpt4 book ai didi

python - 从 .py 文件中提取 Python 函数名称、主体和文档类型

转载 作者:行者123 更新时间:2023-12-05 05:02:12 26 4
gpt4 key购买 nike

我已经使用 Python 编程多年,但是,我刚刚了解到您可以使用如下命令:

<function>.__doc__

返回 Python 函数的文档字符串!但是,这仍然不足以完成我想要完成的任务。我需要能够提取特定 .py 文件中定义的每个函数的名称,并提取函数名称文档字符串和主体。例如,假设我有以下 .py 文件:

import numpy as np

def get_palindrome(string):
"""Returns the palindrome of the string argument"""
return string[::-1]

def break_my_computer():
"""Destroys your RAM"""
a = []
while True:
a.append(1)

这应该能够返回以下信息:

info = {1: {
'name': 'get_palindrome',
'docstring': 'Returns the palindrome of the string argument',
'body': 'return string[::-1]'
},
2: {
'name': 'break_my_computer',
'docstring': 'Destroys your RAM',
'body': 'a = []\nwhile True:\n a.append(1)'
} }

在 Python 中获取此信息的最简单方法是什么(我最好不想使用正则表达式库或进行任何文本解析和匹配)。

注意:当遇到多行文档字符串或函数体时,\n(换行符)命令应该出现在相应的输出中;制表符应由命令或空格表示。

最佳答案

正确答案是 - 不要这样做!

无论如何我都会去做。

你的问题的前两部分很简单,所以我先把它弄清楚:

import inspect

import module_name as module
# This bit is for if you want to load the module from a file by path, mutually exclusive with previous line
# import importlib
#
# spec = importlib.util.spec_from_file_location("module_name", "/path/to/module_name.py")
# module = importlib.util.module_from_spec(spec)
# spec.loader.exec_module(module)

funcs = []
for name, value in vars(module).items():
if name.startswith("_") or not callable(value):
continue
doc = inspect.getdoc(value)
code = marshal.dumps(value.__code__)
funcs.append({"name": name, "docstring": doc, "body": code})

现在我们到达了难点 - body。无法直接阅读源代码,因为 Python 根本不存储它。您当然可以使用 getsource 读取该文件。但这不适用于自从 python 加载后在磁盘上修改过的模块。如果您想采用这种方法,请遵循以下代码:

import inspect

import module_name as module
# This bit is for if you want to load the module from a file by path, mutually exclusive with previous line
# import importlib
#
# spec = importlib.util.spec_from_file_location("module_name", "/path/to/module_name.py")
# module = importlib.util.module_from_spec(spec)
# spec.loader.exec_module(module)

funcs = []
for name, value in vars(module).items():
if name.startswith("_") or not callable(value):
continue
doc = inspect.getdoc(value)
code = inspect.getsource(value).split(":", maxsplit=1)[1]
funcs.append({"name": name, "docstring": doc, "body": code})
print(funcs)

解决这个问题的最好办法就是根本不存储源代码。您应该改为使用 marshal 模块来序列化代码。这在 python 的主要版本之间中断,是一种丑陋的 hack。如果有任何方法可以避免存储函数代码,请这样做,因为它存在安全风险。

包括编码的完整代码:

import inspect
import marshal
import types

import module_name as module
# This bit is for if you want to load the module from a file by path, mutually exclusive with previous line
# import importlib
#
# spec = importlib.util.spec_from_file_location("module_name", "/path/to/module_name.py")
# module = importlib.util.module_from_spec(spec)
# spec.loader.exec_module(module)

funcs = []
for name, value in vars(module).items():
if name.startswith("_") or not callable(value):
continue
doc = inspect.getdoc(value)
code = marshal.dumps(value.__code__)
funcs.append({"name": name, "docstring": doc, "body": code})

for value in funcs:
name = value["name"]
doc = value["docstring"]
code = value["body"]
# invoke all the functions
func = types.FunctionType(marshal.loads(code), globals(), name)
func.__doc__ = doc
func()

关于python - 从 .py 文件中提取 Python 函数名称、主体和文档类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62284638/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com