2009-09-26 118 views
10

我想用Python解釋器破解並嘗試創建一個小的DSL。有沒有什麼模塊可以做這種理論代碼(類似於LINQ表達式樹)?有什麼辦法以編程方式生成Python字節碼?

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

或者只是簡單地生成Python源代碼?使用C或SWIG或Cython可以使這更容易嗎?

+0

鑑於面嚮對象語言(特別是Python)的巨大表現力,DSL相當愚蠢。只需編寫Python。如果你爲自己提供了好的類定義,那麼你就有了一個「類DSL」的Python,並且不需要它。 – 2009-09-27 23:27:53

回答

10

通過ast工作並將樹編譯爲字節碼,正如另一個答案所暗示的,可能是最簡單的;生成資源並進行編譯,幾乎一樣好。

但是,要探索較低級別的方法,請查看this page;我發現byteplay特別有用(目前不適用於2.6或3. *,只有2.4或2.5,但我認爲修復2.6應該很容易,正如其跟蹤器中討論的那樣)。我沒有使用Phil Eby的類似功能BytecodeAssembler,但考慮到作者的聲譽,我相信這是值得檢查!

+0

+1尼斯鏈接:) – 2009-09-27 00:42:21

+0

一如既往的好回答。 :-) – 2009-09-27 12:58:28

0

退房拆裝模塊這裏找到:

http://docs.python.org/library/dis.html

+0

唯一的是我想組裝字節碼,而不是* dis *組裝它。 :-) – 2009-09-27 13:04:58

+0

ahh好點,對不起);但是反彙編模塊的好處是它可以讓你看看生成的字節碼,並給出字節碼指令的細節。 – Nope 2009-09-27 18:44:40

5

在Python 2.X,你通常會與compiler module及其ast子模塊處理這個(但要注意這個模塊,因爲版本已經過時2.6)。在Python 3.X中,你只能使用ast

兩者都提供compile()函數,該函數將從source/AST轉換爲「可由exec語句或eval()執行的代碼對象」。

1

Fernando Meyer recently wrote a blog post解釋如何使用# 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) 
2

它更容易生成Python代碼並運行它。如果你這樣做,你也可以更容易地調試它,因爲調試器有實際的來源顯示。另請參閱Malte Borchs在Python雜誌七月號的文章,他在其中談論了這一點。

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)