调用python库函数的过程

时间:2016-02-17 23:18:22

标签: python bytecode

我试图理解调用python函数的过程,我创建了调用.pyc的简单os.listdir('.')文件, 我看到oslistdir保存在co_names表中,执行CALL_FUNCTION字节码指令时,如何识别os库?它的名字是使用co_names表吗?是python开始搜索名为os.pyc的模块?如果是这样,python如何知道.pyc模块中调用的函数的字节码的偏移量在哪里?

感谢。

dis module bytecode snippet

  5          28 LOAD_NAME                0 (os)
             31 LOAD_ATTR                2 (listdir)
             34 LOAD_CONST               3 ('.')
             37 CALL_FUNCTION            1

1 个答案:

答案 0 :(得分:4)

Python的虚拟机是基于堆栈的。对Python对象的引用被压入堆栈,并且操作码将其中的一个或多个关闭,执行某些操作,并且通常将结果推回堆栈以供下一个操作码使用。

顺便说一句,你可能会发现一个简单的算术计算很有趣(操作必须完全重新排序才能以这种格式工作)。或者阅读FORTH; Python的VM与FORTH没有什么不同,但实际的FORTH 语言以一种Python的方式反映了它的VM。无论如何,关于解释......

LOAD_NAME操作码获取对os对象的引用。 (它恰好是一个模块,但它与什么类型的对象无关,它对所有类型的对象都有效。)引用放在堆栈的顶部。

(这不会搜索或加载模块.Python已经使用先前的os语句导入了对import的引用,并且只是从全局变量中检索此引用。)< / p>

LOAD_ATTR操作码获取对堆栈顶部引用的任何对象的listdir对象的引用。 (同样,这个引用是一个函数,但这并不重要。)弹出堆栈顶部的对象引用,并推送LOAD_ATTR的结果。

LOAD_CONST操作码获取对字符串'.'的引用,并将其推送到堆栈顶部。

现在CALL_FUNCTION弹出1引用堆栈。这是对'.'字符串os.listdir的引用。 (它知道弹出1引用,因为CALL_FUNCTION的操作数是1.如果函数占用更多参数,则会有更多LOAD个操作码,CALL_FUNCTION操作码的操作数会更高。)它从堆栈中弹出另一个引用,这是对os.listdir函数的引用。然后它使用参数调用该函数。然后,函数的返回值被压入堆栈,在那里它可以被其他操作码使用。

正如您所发现的,名称oslistdir存储在表co_names中。 LOAD_NAMELOAD_ATTR操作码的操作数是此表的索引。 '.'的处理方式类似,但它存储在co_consts表中。