[英]How to get a list of classes and functions from a python file without importing it
我有一個 python 文件,其中定義了一些類和函數:
class A(object):
def __init__(self, an_arg, a_default_arg=None):
pass
def doStuff(an_other_arg, an_other_default_arg=None):
pass
我想得到這個文件中所有類和函數的列表。 (他們的名字和參數定義就夠了)
現在,我知道您可以使用__import__(module_descriptor)
和inspect
來執行此操作,但這不是一個選項,因為我正在掃描的文件來自不受信任的來源。
我的第一反應是嘗試創建一個安全的環境來導入它們,但根據其他 stackoverflow 問題,這似乎是不可能的。
您可以使用ast模塊來解析源文件,而無需實際執行任何代碼。 然后您可以遍歷節點樹以獲取函數和類名稱/參數。
import ast
def show_info(functionNode):
print("Function name:", functionNode.name)
print("Args:")
for arg in functionNode.args.args:
#import pdb; pdb.set_trace()
print("\tParameter name:", arg.arg)
filename = "untrusted.py"
with open(filename) as file:
node = ast.parse(file.read())
functions = [n for n in node.body if isinstance(n, ast.FunctionDef)]
classes = [n for n in node.body if isinstance(n, ast.ClassDef)]
for function in functions:
show_info(function)
for class_ in classes:
print("Class name:", class_.name)
methods = [n for n in class_.body if isinstance(n, ast.FunctionDef)]
for method in methods:
show_info(method)
結果:
Function name: doStuff
Args:
Parameter name: an_other_arg
Parameter name: an_other_default_arg
Class name: A
Function name: __init__
Args:
Parameter name: self
Parameter name: an_arg
Parameter name: a_default_arg
除了實際執行文件之外,沒有什么可以為您提供對這個問題的 100% 准確答案。 Python 中有太多方法可以動態影響命名空間:從別處導入名稱、有條件地執行定義、通過修改__dict__
直接操作命名空間等。
如果您只能接受靜態定義,那么 Python 的內置ast
(抽象語法樹)模塊可能是最簡單的解決方案。 您可以安全地將文件編譯為 AST,然后在其頂層查找def
和class
語句。 (在類的情況下,您將在類主體中尋找def __init__
。不要忘記類沒有自己的__init__
,而只是從超類繼承一個的可能性!)
接受的解決方案是不完整的。 考慮以下文件:
def regular_function():
def nested_function():
pass
async def async_function():
pass
接受的解決方案只會打印:
Function name: regular_function
Args:
要獲取所有功能,我們需要進行兩個更改:
async
函數和常規函數這是更正后的代碼,用於查找函數:
import ast
from pathlib import Path
parsed_ast = ast.parse(Path(__file__).read_text())
functions = [
node
for node in ast.walk(parsed_ast)
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
]
for function in functions:
print(f"Function name: {function.name}")
print(f"Args: {', '.join([arg.arg for arg in function.args.args])}")
請注意,這違反了 AST walk 的用途。 對於更復雜的事情,請考慮使用NodeVisitor
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.