gc、inspect 与 dis 运行时工具
Python gc inspect dis 的完整教学讲解。
gc 垃圾回收
基本写法:手动回收
gc.collect()
# 触发垃圾回收
import gc
print(gc.collect()) # 返回回收对象数
基本写法:分代回收
gc.collect(<代>)
# 只回收指定代(0/1/2)
gc.collect(0)
基本写法:获取对象引用
gc.get_referrers(<对象>)
# 获取引用指定对象的对象
class Obj: pass
o = Obj()
lst = [o]
print(gc.get_referrers(o))
基本写法:获取引用对象
gc.get_referents(<对象>)
# 获取对象引用的对象
print(gc.get_referents(lst))
基本写法:获取阈值
gc.get_threshold()
# 获取分代回收阈值
print(gc.get_threshold()) # (700, 10, 10)
基本写法:设置阈值
gc.set_threshold(<阈值0>, <阈值1>, <阈值2>)
# 调整回收阈值
gc.set_threshold(1000, 15, 15)
基本写法:禁用/启用
gc.disable() | gc.enable()
# 禁用自动 GC
gc.disable()
gc.enable()
基本写法:调试标志
gc.set_debug(<标志>)
# 设置调试输出
gc.set_debug(gc.DEBUG_LEAK)
基本写法:跟踪对象
gc.callbacks.append(<回调>)
# 注册 GC 回调
def on_gc(phase, info):
print(phase, info)
gc.callbacks.append(on_gc)
基本写法:循环引用检测
gc.garbage
# 有 __del__ 的循环引用对象列表
print(gc.garbage)
inspect 检查
基本写法:获取源码
inspect.getsource(<对象>)
# 获取函数/类的源代码
import inspect
def foo():
pass
print(inspect.getsource(foo))
基本写法:获取文件
inspect.getfile(<对象>)
# 获取对象定义所在文件
print(inspect.getfile(foo))
基本写法:获取模块
inspect.getmodule(<对象>)
# 获取对象所属模块
print(inspect.getmodule(foo))
基本写法:签名信息
inspect.signature(<函数>)
# 获取函数签名
def add(a, b=10):
return a + b
sig = inspect.signature(add)
print(sig.parameters)
基本写法:参数详情
inspect.Parameter
# 检查参数
for name, p in sig.parameters.items():
print(name, p.kind, p.default)
基本写法:是否为函数/类
inspect.isfunction(<对象>) | inspect.isclass(<对象>)
# 类型判断
print(inspect.isfunction(foo))
print(inspect.isclass(int))
基本写法:成员列表
inspect.getmembers(<对象>, <谓词>)
# 获取对象成员
class A:
def method(self): pass
for name, member in inspect.getmembers(A, inspect.isfunction):
print(name)
基本写法:获取类层级
inspect.getmro(<类>)
# 获取方法解析顺序
print(inspect.getmro(int))
基本写法:获取调用栈
inspect.stack()
# 获取调用栈帧
def outer():
inner()
def inner():
for frame in inspect.stack():
print(frame.function)
outer()
基本写法:当前帧
inspect.currentframe()
# 获取当前帧
frame = inspect.currentframe()
print(frame.f_code.co_name)
dis 字节码反汇编
基本写法:反汇编函数
dis.dis(<函数>)
# 反汇编为字节码
import dis
def add(a, b):
return a + b
dis.dis(add)
基本写法:反汇编字符串代码
dis.dis(<代码字符串>)
# 反汇编代码字符串
dis.dis("a + b")
基本写法:获取字节码
dis.Bytecode(<函数>)
# 获取 Bytecode 对象迭代
for instr in dis.Bytecode(add):
print(instr.opname, instr.argval)
基本写法:查看常量
dis.code_info(<函数>)
# 获取代码对象信息
print(dis.code_info(add))
基本写法:show_code
dis.show_code(<函数>)
# 打印代码对象信息
dis.show_code(add)
ast 抽象语法树
基本写法:解析代码
ast.parse(<代码字符串>)
# 解析为 AST
import ast
tree = ast.parse("x = 1 + 2")
print(ast.dump(tree))
基本写法:遍历节点
ast.walk(<树>)
# 遍历所有节点
for node in ast.walk(tree):
print(type(node).__name__)
基本写法:NodeVisitor 访问
class <类>(ast.NodeVisitor):\n def visit_<节点>(self, node):
# 自定义访问器
class Counter(ast.NodeVisitor):
def __init__(self):
self.count = 0
def visit_Call(self, node):
self.count += 1
self.generic_visit(node)
c = Counter()
c.visit(ast.parse("a(); b()"))
print(c.count)
基本写法:NodeTransformer 修改
class <类>(ast.NodeTransformer):
# 修改 AST 节点
class Double(ast.NodeTransformer):
def visit_Num(self, node):
return ast.copy_location(ast.Num(n=node.n * 2), node)
基本写法:unparse 反向生成
ast.unparse(<树>)
# AST 转回代码字符串(3.9+)
print(ast.unparse(tree))
基本写法:literal_eval 安全求值
ast.literal_eval(<字符串>)
# 安全求值字面值
print(ast.literal_eval("[1, 2, 3]"))
print(ast.literal_eval("{'a': 1}"))
sys.intern 字符串驻留
基本写法:字符串驻留
sys.intern(<字符串>)
# 字符串驻留,节省内存
import sys
a = sys.intern("hello")
b = sys.intern("hello")
print(a is b) # True
sys.getsizeof 对象大小
基本写法:获取对象大小
sys.getsizeof(<对象>)
# 获取对象字节大小
print(sys.getsizeof([1, 2, 3]))
print(sys.getsizeof("hello"))
基本写法:递归大小
sys.getsizeof(<对象>, <默认>)
# 配合递归计算容器总大小
def total_size(obj):
seen = set()
def inner(o):
if id(o) in seen:
return 0
seen.add(id(o))
s = sys.getsizeof(o)
if isinstance(o, (list, tuple, set)):
s += sum(inner(i) for i in o)
return s
return inner(obj)