我已经使用Python编程了几年,但是我刚刚了解到您可以使用以下命令:
<function>.__doc__
返回Python函数的文档字符串!但是,这仍然不足以完成我要完成的任务。我需要能够提取在特定.py文件中定义的每个函数的名称,并提取函数名称docstring和body。例如,考虑我有以下.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
# 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)
func.append({"name": name, "docstring": doc})
现在我们到达最困难的部分-body
。无法直接读取源代码,因为Python只是不存储它。您当然可以使用getsource读取文件,但这不适用于自python加载后在磁盘上修改的模块。如果您想采用这种方法,那么实现自己就很简单。
此问题的最佳解决方案是根本不存储源代码。相反,您应该使用marshal
模块来序列化代码。在Python的主要版本之间的这个[[will中断,有点丑陋。如果有任何方法可以避免存储函数代码,请这样做,因为这样做存在安全风险。
import inspect
import marshal
import types
import module_name
# 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__)
func.append({"name": name, "docstring": doc, "body": code})
for name, doc, code in funcs:
# invoke all the functions
func = types.FunctionType(code, globals(), name)
func.__doc__ = doc
func()