有没有办法通过编程生成Python字节码?
我想尝试一下Python解释器,并尝试创建一个小型DSL。是否有任何模块可以执行类似于此理论代码(类似于LINQ表达式树)的操作有没有办法通过编程生成Python字节码?,python,expression-trees,abstract-syntax-tree,dsl,bytecode,Python,Expression Trees,Abstract Syntax Tree,Dsl,Bytecode,我想尝试一下Python解释器,并尝试创建一个小型DSL。是否有任何模块可以执行类似于此理论代码(类似于LINQ表达式树)的操作 或者仅仅生成Python源代码会更容易吗?使用C、SWIG或Cython是否可以简化此操作?查看此处的反汇编程序模块: 在Python2.X中,您通常会使用及其ast子模块来实现这一点(但请注意,自版本2.6以来,此模块已被弃用)。在Python3.X中,您将使用just 两者都提供了一个compile()函数,该函数将从source/AST转换为“可由exec语句或
或者仅仅生成Python源代码会更容易吗?使用C、SWIG或Cython是否可以简化此操作?查看此处的反汇编程序模块:
在Python2.X中,您通常会使用及其
ast
子模块来实现这一点(但请注意,自版本2.6以来,此模块已被弃用)。在Python3.X中,您将使用just
两者都提供了一个compile()
函数,该函数将从source/AST转换为“可由exec
语句或eval()
执行的代码对象”,解释如何使用\coding
指令指定自己的Python扩展。示例(实际格式定义在和中):
生成Python代码并运行它更容易。如果这样做,还可以更轻松地调试它,因为有实际的源代码可供调试器显示。另请参阅Malte Borchs在Python杂志7月号上的文章,他在文章中谈到了这一点。另一个答案是,通过
ast
工作并将树编译成字节码可能是最简单的;生成源代码并编译它们,几乎一样好
但是,要探索较低级别的方法,请查看以下链接:;我发现它特别有用(目前在2.6和3上都不起作用。*,只有2.4或2.5,但我认为在2.6上修复它应该很容易,正如目前在其跟踪器中讨论的那样)。我没有使用Phil Eby的类似功能,但考虑到作者的声誉,我相信值得一看 Python3的更新-还有一个非常有趣的汇编程序 事实上,在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)
>导入byteasm,dis
>>>b=byteam.FunctionBuilder()
>>>b.添加位置参数('x')
>>>b.emit\u load\u const('Hello!')
>>>b.快速释放负载('x')
>>>b.emit\u build\u元组(2)
>>>b.发射返回值()
>>>f=b.make('f')
>>>f
>>>dis.dis(f)
1 0加载常数0('Hello!')
3加载速度为0(x)
6构建元组2
9返回值
>>>f(108)
(‘你好!’,108)
唯一的问题是我想汇编字节码,而不是反汇编。:-)啊,说得好,很抱歉;)然而,反汇编模块的好处在于,它可以让您查看生成的字节码以及字节码指令的细节。鉴于OO语言(尤其是Python)的巨大表达能力,DSL是相当愚蠢的。只需编写Python。如果你为自己提供好的类定义,你就有一个“类似DSL”的Python,而不需要它。我们在DSL方面的效率更高。参见“代码完成”软件构造的圣经。
# 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)
>>> 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)