获取源脚本详细信息,类似于inspect.getmembers()而不导入脚本 [英] Get source script details, similar to inspect.getmembers() without importing the script
问题描述
我正在尝试在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屋!