2017-09-02 47 views
-1

在python3,我有以下代码:python3:从代码对象获取已定义的函数?

path = '/path/to/file/containing/python/code' 
source = open(path, 'r').read() 
codeobject = compile(source, path, 'exec') 

我已经研究codeobject,但我看不出有什么办法让那些该对象中定义的所有功能的列表。

我知道我可以搜索source字符串,以def开头的行,但我想从代码对象中获取此信息,如果可能的话。

我缺少什么?

+0

那么你的目标是什么?列出所有代码对象的部分功能名称?或者提取这些函数的所有代码? –

回答

1

代码对象是嵌套结构;功能创建当执行代码对象,用他们的身体嵌入作为属于常数的一部分单独的代码对象:

>>> example = '''\ 
... def foobar(): 
...  print('Hello world!') 
... ''' 
>>> codeobject = compile(example, '', 'exec') 
>>> codeobject 
<code object <module> at 0x11049ff60, file "", line 1> 
>>> codeobject.co_consts 
(<code object foobar at 0x11049fe40, file "", line 1>, 'foobar', None) 
>>> codeobject.co_consts[0] 
<code object foobar at 0x11049fe40, file "", line 1> 
>>> codeobject.co_consts[0].co_name 
'foobar' 

当拆卸顶级代码对象你可以看到,功能对象从这样的代码对象被创建:

>>> import dis 
>>> dis.dis(codeobject) 
    1   0 LOAD_CONST    0 (<code object foobar at 0x11049fe40, file "", line 1>) 
       2 LOAD_CONST    1 ('foobar') 
       4 MAKE_FUNCTION   0 
       6 STORE_NAME    0 (foobar) 
       8 LOAD_CONST    2 (None) 
      10 RETURN_VALUE 

MAKE_FUNCTION opcode需要从堆栈代码对象,以及函数名和从堆栈中任何默认参数值;你可以在它之前看到LOAD_CONST opcodes,它将代码对象和名称放在那里。

并非所有的代码对象是函数但是:

>>> compile('[i for i in range(10)]', '', 'exec').co_consts 
(<code object <listcomp> at 0x1105cb030, file "", line 1>, '<listcomp>', 10, None) 
>>> compile('class Foo: pass', '', 'exec').co_consts 
(<code object Foo at 0x1105cb0c0, file "", line 1>, 'Foo', None) 

如果要列出哪些功能在字节码被加载,你最好的办法是使用反汇编,而不是找代码对象:

这会为加载到给定代码对象中的所有函数生成(name, codeobject)元组。

+0

我明白了。但并不是co_consts列表中的所有项都是代码对象。我不知道如何检查每一个的类型以查看它们是嵌套的代码对象还是其他东西。 '如果type(codeobject [0])是什么:'???我试过'如果type(codeobject [0])是代码:',但失败了。 – HippoMan

+0

@HippoMan:'type(codeobject)'给你正确的类型。 –

+0

是的,但是我要比较'type(codeobject)'到什么?什么是Python类型的名称? 'type(codeobject)是什么'?在if语句中,我应该用什么替换“WHAT”? – HippoMan