从 Python 3 中的代码对象中提取所有常量
Extracting all constants from code object in Python 3
我想提取函数中使用的所有常量。在 Python 2.7 中,我可以在函数的 __code__
中遍历 co_consts
并提取所有字符串。例如,
Python2.7
>>> def func():
...: return 'foo' if True else ('bar',)
>>> print(func.__code__.co_consts)
(None, 'foo', 'bar', ('bar',)) # no need to look into the tuple as 'bar' is available outside it as well.
这将按预期给我 'foo'
和 'bar'
。但是,在 Python 3.7
中,代码对象仅在元组内部包含 'bar'
。
Python 3.7
>>> print(func.__code__.co_consts)
(None, True, 'foo', ('bar',))
这意味着我还需要查看 co_consts 中的元组。我的困惑是 co_consts
?
中是否可以有更多级别的嵌套
你可以递归地遍历 co_consts
元组然后:
def x():
return {
"y": ("bla" + "ble", ("blo", ["blu", "blip"])),
("x", "z"): "blup",
True: False,
42: "hello" * 10,
None: 4 + 1j,
}
def get_consts(func):
def walk(cell):
if isinstance(cell, tuple):
for item in cell:
yield from walk(item)
else:
yield cell
yield from walk(func.__code__.co_consts)
for const in get_consts(x):
print(const)
打印
None
blable
blo
blu
blip
blup
False
hellohellohellohellohellohellohellohellohellohello
(4+1j)
y
x
z
True
42
None
常数的顺序可能与原始来源中的顺序不同;它们确实对应于反汇编中的顺序:
5 0 LOAD_CONST 1 ('blable')
2 LOAD_CONST 2 ('blo')
4 LOAD_CONST 3 ('blu')
6 LOAD_CONST 4 ('blip')
8 BUILD_LIST 2
10 BUILD_TUPLE 2
12 BUILD_TUPLE 2
6 14 LOAD_CONST 5 ('blup')
7 16 LOAD_CONST 6 (False)
8 18 LOAD_CONST 7 ('hellohellohellohellohellohellohellohellohellohello')
9 20 LOAD_CONST 8 ((4+1j))
22 LOAD_CONST 9 (('y', ('x', 'z'), True, 42, None))
24 BUILD_CONST_KEY_MAP 5
26 RETURN_VALUE
编辑:如果您需要源代码中的原始字符串,则需要改用 ast
模块:
import ast
import inspect
class ConstantGatherer(ast.NodeVisitor):
def __init__(self):
super().__init__()
self.consts = []
def visit_Str(self, node):
self.consts.append(node.s)
def visit_Num(self, node):
self.consts.append(node.n)
cg = ConstantGatherer()
cg.visit(ast.parse(inspect.getsource(x)))
print(cg.consts)
产出
['y', 'x', 'z', 42, 'bla', 'ble', 'blo', 'blu', 'blip', 'blup', 'hello', 10, 4, 1j]
如何在下面的代码中使用 inspect
从函数 f
中获取常量参数值 3
?
def l2_norm(x, axis):
print("l2_norm", x, axis)
f = lambda x: l2_norm(x, axis=3)
我想提取函数中使用的所有常量。在 Python 2.7 中,我可以在函数的 __code__
中遍历 co_consts
并提取所有字符串。例如,
Python2.7
>>> def func():
...: return 'foo' if True else ('bar',)
>>> print(func.__code__.co_consts)
(None, 'foo', 'bar', ('bar',)) # no need to look into the tuple as 'bar' is available outside it as well.
这将按预期给我 'foo'
和 'bar'
。但是,在 Python 3.7
中,代码对象仅在元组内部包含 'bar'
。
Python 3.7
>>> print(func.__code__.co_consts)
(None, True, 'foo', ('bar',))
这意味着我还需要查看 co_consts 中的元组。我的困惑是 co_consts
?
你可以递归地遍历 co_consts
元组然后:
def x():
return {
"y": ("bla" + "ble", ("blo", ["blu", "blip"])),
("x", "z"): "blup",
True: False,
42: "hello" * 10,
None: 4 + 1j,
}
def get_consts(func):
def walk(cell):
if isinstance(cell, tuple):
for item in cell:
yield from walk(item)
else:
yield cell
yield from walk(func.__code__.co_consts)
for const in get_consts(x):
print(const)
打印
None
blable
blo
blu
blip
blup
False
hellohellohellohellohellohellohellohellohellohello
(4+1j)
y
x
z
True
42
None
常数的顺序可能与原始来源中的顺序不同;它们确实对应于反汇编中的顺序:
5 0 LOAD_CONST 1 ('blable')
2 LOAD_CONST 2 ('blo')
4 LOAD_CONST 3 ('blu')
6 LOAD_CONST 4 ('blip')
8 BUILD_LIST 2
10 BUILD_TUPLE 2
12 BUILD_TUPLE 2
6 14 LOAD_CONST 5 ('blup')
7 16 LOAD_CONST 6 (False)
8 18 LOAD_CONST 7 ('hellohellohellohellohellohellohellohellohellohello')
9 20 LOAD_CONST 8 ((4+1j))
22 LOAD_CONST 9 (('y', ('x', 'z'), True, 42, None))
24 BUILD_CONST_KEY_MAP 5
26 RETURN_VALUE
编辑:如果您需要源代码中的原始字符串,则需要改用 ast
模块:
import ast
import inspect
class ConstantGatherer(ast.NodeVisitor):
def __init__(self):
super().__init__()
self.consts = []
def visit_Str(self, node):
self.consts.append(node.s)
def visit_Num(self, node):
self.consts.append(node.n)
cg = ConstantGatherer()
cg.visit(ast.parse(inspect.getsource(x)))
print(cg.consts)
产出
['y', 'x', 'z', 42, 'bla', 'ble', 'blo', 'blu', 'blip', 'blup', 'hello', 10, 4, 1j]
如何在下面的代码中使用 inspect
从函数 f
中获取常量参数值 3
?
def l2_norm(x, axis):
print("l2_norm", x, axis)
f = lambda x: l2_norm(x, axis=3)