有没有一种编程方式可以自动生成Python字节码?

12

我想尝试使用Python解释器并创建一个小型DSL。是否有任何模块可以让我做类似于这个理论代码(类似于LINQ表达式树)的事情?

expression_tree = Function(
    Print(
        String('Hello world!')
    )
 )
compile_to_bytecode(expression_tree)

或者只是生成Python源代码会更容易吗?使用C、SWIG或Cython能否使这个过程更简单?


鉴于面向对象语言(特别是Python)具有巨大的表达能力,DSL相当愚蠢。只需编写Python即可。如果您提供了良好的类定义,您就拥有了“类似DSL”的Python,不需要使用DSL。 - S.Lott
DSL(领域特定语言)从来不是愚蠢的。我们在DSL中更加高效。请参考《代码大全》,这是软件构建的圣经。 - MicroservicesOnDDD
6个回答

13

通过使用ast并将树编译成字节码,正如另一个答案所建议的那样,可能是最简单的方法;生成源代码并进行编译,几乎同样好。

但是,如果想要探索更低级别的方法,请查看此页面中的链接;我发现byteplay特别有用(目前无法在2.6或3.*上工作,仅适用于2.4或2.5,但我认为在其跟踪器中当前正在讨论很容易修复为2.6)。我没有使用Phil Eby的类似功能的BytecodeAssembler,但考虑到作者的声誉,我相信值得一试!


5
在Python 2.X中,您通常会使用compiler模块及其ast子模块来处理此问题(但请注意,自2.6版本以后,此模块已被弃用)。在Python 3.X中,您只需要使用ast

两者都提供了一个compile()函数,可以将源代码/AST转换为“可由exec语句或eval()执行的代码对象”。

2

生成Python代码并运行它更容易。如果这样做,您还可以更轻松地调试它,因为调试器有实际的源代码来显示。另请参见Python杂志7月号中Malte Borch的文章,其中他谈到了这个问题以及其他内容。


1

更新至Python3 - 还有一个非常有趣的汇编程序zachariahreed/byteasm

实际上,这是我在Py3中唯一能用的。它具有非常好的、清晰的API:

>>> import byteasm, dis
>>> b = byteasm.FunctionBuilder()
>>> b.add_positional_arg('x')
>>> b.emit_load_const('Hello!')
>>> b.emit_load_fast('x')
>>> b.emit_build_tuple(2)
>>> b.emit_return_value()
>>> f = b.make('f')
>>> f
<function f at 0xb7012a4c>
>>> dis.dis(f)
  1           0 LOAD_CONST               0 ('Hello!')
              3 LOAD_FAST                0 (x)
              6 BUILD_TUPLE              2
              9 RETURN_VALUE
>>> f(108)
('Hello!', 108)

1

Fernando Meyer 最近写了一篇博客文章,解释了如何使用 # coding 指令来指定自己的 Python 扩展。示例(实际格式定义在 pyspec.pytokenizer.py 中):

# coding: pyspec

class Bow:
    def shot(self):
        print "got shot"

    def score(self):
        return 5

describe Bowling:
    it "should score 0 for gutter game":
        bowling = Bow()
        bowling.shot()
        assert that bowling.score.should_be(5)

0

唯一的问题是我想要组装字节码,而不是反汇编它。 :-) - Jason Baker
啊,好观点,对此我很抱歉 ;) 不过反汇编模块的好处在于它让你查看生成的字节码,并提供字节码指令的具体信息。 - Nope

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接