跳转到主要内容

Python模块,用于处理字节码

项目描述

bytearound是一个模块,用于组装和反汇编CPython 2.7.11的字节码。它提供了一种比CPython内部表示和功能更易于修改、创建和检查的字节码表示形式,并提供了在字节码表示和CPython代码对象之间转换的功能。

创建代码的示例

from bytearound import ByteAround, Instruction, ops

ba = ByteAround([
    ops.LOAD_CONST('Hello World!'),
    ops.PRINT_ITEM(),
    ops.PRINT_NEWLINE(),
    ops.LOAD_CONST(None),
    ops.RETURN_VALUE(),
])
exec(ba.to_code())

以及简单的修改

from bytearound import ByteAround

def f():
    print 'Hello World!'

ba = ByteAround.from_code(f.func_code)
for instr in ba:
    if instr.oparg == 'Hello World!':
        instr.oparg = 'Goodbye World!'
f.func_code = ba.to_code()
f()

设计和限制

我设计和编写了bytearound,以确保co == ByteAround.from_code(co).to_code()始终成立——也就是说,将Python代码对象转换为bytearound表示形式,然后转换回来应该给出相同的代码对象。确保此不变性成立使得测试代码的正确性更加容易。存在一个名为debug.check()的函数来检查此不变性。

不幸的是,CPython生成代码对象的方式存在一些怪癖,这些怪癖很难复制。为了复制其中的一些,我向ByteAround.to_code添加了一个pessimize=参数,它试图在效率稍高的情况下也忠实地复制CPython,并创建了一个自定义比较函数,它忽略了其他一些已知问题。但是,可能无法通过这些方法消除所有细微差异。已知问题包括

  • CPython在运行窥孔优化器之前会计算代码对象的一些部分,这可能导致co_stacksize过高(因为窥孔优化器可以将构建元组的多个操作码转换为单个LOAD_CONST操作码)。同样的问题也可能影响co_consts字段顺序,显然是因为优化器将新常量添加到列表的末尾。同样,对常量的数学运算(例如2 ** 32)可能被窥孔优化器优化掉,可能留下不必要的常量。

  • 当在函数中使用像None和True这样的单例对象时,CPython会将它们的名称添加到co_names字段(不必要地,因为对象是直接通过LOAD_CONST加载的),并将常量添加到co_consts列表的末尾。(通常,co_consts按照常量在函数中首次出现顺序包含常量。)然而,None作为常量的某些其他用法被放置在co_consts的正确位置。

  • 类似(f(x) for x in y)这样的单行生成器表达式的代码对象具有非空co_lnotab字段,但像“def f(x): print(x)”这样的函数的co_lnotab是空的。在某些其他情况下,CPython还会在co_lnotab中生成不必要的0偏移量条目。

  • 大型opargs(使用EXTENDED_ARG)和大型行号偏移量没有得到很好的测试,并且有一些已知问题,已在代码中注明。

bytearound仅在Python 2.7.11上进行了测试。2.7系列之前的版本应该大多数情况下都能正常工作,但在该系列中的一些更改影响了代码对象(例如问题21523)。

类似模块

  • byteplay(未维护,存在错误)

  • bytecode(仅适用于Python 3,不实现堆栈大小计算)

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装软件包的信息。

源代码分发

bytearound-0.2.tar.gz (12.5 kB 查看哈希)

源代码

由以下组织支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面