获取源脚本详细信息,类似于inspect.getmembers()而不导入脚本 [英] Get source script details, similar to inspect.getmembers() without importing the script

查看:180
本文介绍了获取源脚本详细信息,类似于inspect.getmembers()而不导入脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在python脚本中获取函数的源,被调用者列表,默认值,关键字,args和varargs。

I'm trying to get the source, callee list, defaults, keywords, args and varargs of the functions in a python script.

目前,我是导入模块并使用python inspect 模块的 getmembers 函数并传递 isfunction 参数如下:

Currently, I'm importing the module and using the python inspect module's getmembers function and passing the isfunction parameter like so:

members = inspect.getmembers(myModule, inspect.isfunction)

但是,如果 myModule 的导入量不足,则此方法不起作用我可以使用(因为 myModule 必须先导入)。

However, this method doesn't work if myModule's imports aren't available to me (since myModule has to be imported first).

我尝试使用python ast 模块到解析 dump 语法树,但得到了功能源涉及非常hacky技术和/或可疑的,远非可维护的第三方库。我相信我已经彻底搜索了文档和stackoverflow,但未能找到合适的解决方案。我错过了什么吗?

I tried using the python ast module to parse and dump the syntax tree, but getting the function source involved very hacky techniques and/or questionable and far from maintainable third party libraries. I believe I've scoured the documentation and stackoverflow pretty thoroughly and have failed to find a suitable solution. Am I missing something?

推荐答案

所以我更多地环顾了一下并快速使用这个家伙的答案,以获取每个功能的来源。它还没有接近完美,但如果你感兴趣的话就在这里:

So I looked around some more and quickly Frankenstein'd a solution using this dude's answer to get each function's source. It isn't anywhere near perfect yet, but here it is if you're interested:

import ast
import re
import json


st = open('filename.py').read()
tree = ast.parse(st)
functions_info = {}


def parse(function):
    global st
    global functions_info
    fn_info = {}
    fn_info['Args'] = []
    fn_info['Source'] = []
    fn_info['Callees'] = []

    print(function.name)

    for arg in function.args.args:
        fn_info['Args'].append(arg.arg)

    lastBody = function.body[-1]

    while isinstance (lastBody,(ast.For,ast.While,ast.If)):
        lastBody = lastBody.Body[-1]
    lastLine = lastBody.lineno

    if isinstance(st,str):
        st = st.split("\n")
    for i , line in enumerate(st,1):
        if i in range(function.lineno,lastLine+1):
            # print(line)
            fn_info['Source'].append(line)

    for line in fn_info['Source']:
        if not line.lstrip().startswith('#'):
            fn_pattern = r'(\w+)\('
            match = re.search(fn_pattern, line)
            if match:
                callee = match.group(1)
                fn_info['Callees'].append(callee)

    functions_info[function.name] = fn_info

for obj in tree.body:
    if isinstance(obj, ast.ClassDef):
        for func in obj.body:
            if isinstance(func, (ast.FunctionDef)):
                parse(func)

    if isinstance(obj, ast.FunctionDef):
        parse(obj)

print(json.dumps(functions_info, indent=4))

输出:

{
    "displayWonder": {
        "Source": [
            "    def displayWonder(self):",
            "        return \"Hello \" + str(self.displayGreeting())"
        ],
        "Args": [
            "self"
        ],
        "Callees": []
    },
    "displayGreeting": {
        "Source": [
            "    def displayGreeting(self):",
            "        string = \"Greetings \" + self.myName",
            "        return string"
        ],
        "Args": [
            "self"
        ],
        "Callees": []
    },
    "myStatic": {
        "Source": [
            "    @staticmethod",
            "    def myStatic():",
            "        return \"I am static\""
        ],
        "Args": [],
        "Callees": []
    },
    "displayHello": {
        "Source": [
            "    def displayHello(self):",
            "        return \"Hello \" + self.myName"
        ],
        "Args": [
            "self"
        ],
        "Callees": []
    },
    "__init__": {
        "Source": [
            "    def __init__(self):",
            "        self.myName = 'Wonder?'"
        ],
        "Args": [
            "self"
        ],
        "Callees": []
    },
    "main": {
        "Source": [
            "def main():",
            "    hello = Hello(\"Wonderful!!!\")",
            "    # name = unicode(raw_input(\"Enter name: \"), 'utf8')",
            "    # print(\"User specified:\", name)",
            "    print(hello.displayGreeting())"
        ],
        "Args": [],
        "Callees": []
    }
}

这篇关于获取源脚本详细信息,类似于inspect.getmembers()而不导入脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆