从.py文件中提取Python函数名称,主体和doctypes

问题描述 投票:0回答:1

我已经使用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(换行符)命令应出现在相应的输出中;选项卡应通过命令或空格来表示。

python function doctype
1个回答
0
投票

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

我还是去做。

您的问题的前两部分非常简单,因此我将首先从头到尾反复说明:

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()

© www.soinside.com 2019 - 2024. All rights reserved.