我想破解Python解释器并尝试创建一个小型DSL。是否有任何模块我可以做这样的理论代码(类似于LINQ表达式树)?
expression_tree = Function(
Print(
String('Hello world!')
)
)
compile_to_bytecode(expression_tree)
或者只是更容易生成Python源代码?使用C或SWIG或Cython可以使这更容易吗?
答案 0 :(得分:11)
通过ast
工作并将树编译成字节码,正如另一个答案所暗示的那样,可能是最简单的;生成源并编译它们几乎一样好。
但是,要探索更低级别的方法,请查看this page的链接;我发现byteplay特别有用(目前不适用于2.6或3. *,只有2.4或2.5,但我认为修复2.6应该很容易,正如其目前在其跟踪器中所讨论的那样)。我没有使用Phil Eby的同样功能BytecodeAssembler,但考虑到作者的声誉,我确信值得一试!
答案 1 :(得分:5)
在Python 2.X中,您通常会使用compiler
module及其ast
子模块来处理此问题(但请注意,自2.6版本以来,此模块已弃用)。在Python 3.X中,您只需使用ast
。
两者都提供compile()
函数,它将从源/ AST转到“可以由exec
语句或eval()
执行的代码对象。”
答案 2 :(得分:2)
生成Python代码并运行它更容易。如果你这样做,你也可以更容易地调试它,因为有调试器的实际来源可以显示。另见Python杂志7月刊中的Malte Borchs文章,其中还讨论了这一点。
答案 3 :(得分:1)
Fernando Meyer recently wrote a blog post解释如何使用# coding
指令指定自己的Python扩展。示例(实际格式定义位于pyspec.py和tokenizer.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)
答案 4 :(得分: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)
答案 5 :(得分:0)
查看此处的反汇编程序模块: