我想破解 Python 解释器并尝试创建一个小的 DSL 。有没有我可以做类似这个理论代码的模块(类似于 LINQ 表达式树)?
expression_tree = Function(
Print(
String('Hello world!')
)
)
compile_to_bytecode(expression_tree)
还是只生成 Python 源代码会更容易?使用 C 或 SWIG 或 Cython 可以使这更容易吗?
我想破解 Python 解释器并尝试创建一个小的 DSL 。有没有我可以做类似这个理论代码的模块(类似于 LINQ 表达式树)?
expression_tree = Function(
Print(
String('Hello world!')
)
)
compile_to_bytecode(expression_tree)
还是只生成 Python 源代码会更容易?使用 C 或 SWIG 或 Cython 可以使这更容易吗?
正如另一个答案所暗示的那样,通过ast
树并将树编译成字节码可能是最简单的;生成源并编译它们,几乎一样好。
但是,要探索较低级别的方法,请查看此页面中的链接;我发现byteplay特别有用(目前在 2.6 和 3.* 上都不起作用,只有 2.4 或 2.5,但我认为为 2.6 修复它应该很容易,正如目前在其跟踪器中所讨论的那样)。我没有使用过 Phil Eby 的类似功能的BytecodeAssembler,但考虑到作者的声誉,我相信它值得一试!
在 Python 2.X 中,您通常会使用compiler
模块及其ast
子模块来处理此问题(但请注意,此模块自 2.6 版以来已弃用)。在 Python 3.X 中,您只需使用ast
.
两者都提供了一个compile()
函数,该函数将从源代码/AST 转换为“可以由exec
语句或eval()
.
生成 Python 代码并运行它更容易。如果你这样做,你也可以更容易地调试它,因为调试器有实际的源来显示。另请参阅 Python 杂志 7 月刊中的 Malte Borchs 文章,他在其中谈到了这一点。
Fernando Meyer 最近写了一篇博文,解释如何使用该# 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)
更新 Python3 - 还有非常有趣的 assembler 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)
查看此处的反汇编模块: