我想用Python解釋器破解並嘗試創建一個小的DSL。有沒有什麼模塊可以做這種理論代碼(類似於LINQ表達式樹)?有什麼辦法以編程方式生成Python字節碼?
expression_tree = Function(
Print(
String('Hello world!')
)
)
compile_to_bytecode(expression_tree)
或者只是簡單地生成Python源代碼?使用C或SWIG或Cython可以使這更容易嗎?
我想用Python解釋器破解並嘗試創建一個小的DSL。有沒有什麼模塊可以做這種理論代碼(類似於LINQ表達式樹)?有什麼辦法以編程方式生成Python字節碼?
expression_tree = Function(
Print(
String('Hello world!')
)
)
compile_to_bytecode(expression_tree)
或者只是簡單地生成Python源代碼?使用C或SWIG或Cython可以使這更容易嗎?
通過ast
工作並將樹編譯爲字節碼,正如另一個答案所暗示的,可能是最簡單的;生成資源並進行編譯,幾乎一樣好。
但是,要探索較低級別的方法,請查看this page;我發現byteplay特別有用(目前不適用於2.6或3. *,只有2.4或2.5,但我認爲修復2.6應該很容易,正如其跟蹤器中討論的那樣)。我沒有使用Phil Eby的類似功能BytecodeAssembler,但考慮到作者的聲譽,我相信這是值得檢查!
+1尼斯鏈接:) – 2009-09-27 00:42:21
一如既往的好回答。 :-) – 2009-09-27 12:58:28
退房拆裝模塊這裏找到:
唯一的是我想組裝字節碼,而不是* dis *組裝它。 :-) – 2009-09-27 13:04:58
ahh好點,對不起);但是反彙編模塊的好處是它可以讓你看看生成的字節碼,並給出字節碼指令的細節。 – Nope 2009-09-27 18:44:40
在Python 2.X,你通常會與compiler
module及其ast
子模塊處理這個(但要注意這個模塊,因爲版本已經過時2.6)。在Python 3.X中,你只能使用ast
。
兩者都提供compile()
函數,該函數將從source/AST轉換爲「可由exec
語句或eval()
執行的代碼對象」。
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)
它更容易生成Python代碼並運行它。如果你這樣做,你也可以更容易地調試它,因爲調試器有實際的來源顯示。另請參閱Malte Borchs在Python雜誌七月號的文章,他在其中談論了這一點。
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)
鑑於面嚮對象語言(特別是Python)的巨大表現力,DSL相當愚蠢。只需編寫Python。如果你爲自己提供了好的類定義,那麼你就有了一個「類DSL」的Python,並且不需要它。 – 2009-09-27 23:27:53