2009-09-26 18 views
10

Je veux pirater avec l'interpréteur Python et essayer de créer un petit DSL. Y at-il un module où je peux faire quelque chose comme ce code théorique (similaire aux arbres d'expression LINQ)?Y at-il un moyen de générer par programme Python bytecode?

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

Ou serait-il simplement plus simple de générer du code source Python? Cela pourrait-il être rendu plus facile en utilisant C ou SWIG ou Cython?

+0

la puissance expressive énorme des langages OO (Python en particulier) une connexion DSL est assez stupide. Écris juste le Python. Si vous fournissez de bonnes définitions de classe, vous avez un Python "DSL-like" et vous n'en avez pas besoin. –

Répondre

10

Travailler via ast et compiler l'arbre en bytecode, comme une autre réponse le suggère, est probablement le plus simple; générer des sources et les compiler, presque aussi bien. Toutefois, pour explorer les approches de niveau inférieur, consultez les liens this page; J'ai trouvé byteplay particulièrement utile (actuellement ne fonctionne pas sur 2.6 ni 3. *, seulement 2.4 ou 2.5, mais je pense que le fixer pour 2.6 devrait être facile, comme actuellement discuté dans son tracker). Je n'ai pas utilisé le BytecodeAssembler similaire de Phil Eby, mais compte tenu de la réputation de l'auteur, je suis sûr qu'il vaut la peine de le vérifier!

+0

+1 Beaux liens :) –

+0

Grande réponse comme toujours. :-) –

0

Vérifiez le module désassembleur trouvé ici:

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

+0

La seule chose est que je voulais assembler bytecode, pas * dis * l'assembler. :-) –

+0

ahh bon point, désolé bout à ce sujet;) mais la bonne chose à propos du module de désassembleur est qu'il vous permet de regarder le bytecode qui est généré ainsi que de donner les détails sur les instructions de bytecode. – Nope

5

En Python 2.X, vous aborderions généralement cela avec le compiler module et son ast sous-module (mais notez ce module est obsolète depuis la version 2.6). En Python 3.X, vous utiliseriez seulement ast.

Les deux offrent une fonction compile() qui ira de source/AST à "un objet de code qui peut être exécuté par l'instruction exec ou eval()".

1

Fernando Meyer recently wrote a blog post Expliquer comment utiliser la directive # coding pour spécifier vos propres extensions à Python. Exemple (la définition du format réel est en pyspec.py et 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) 
2

Il est plus facile de générer du code Python et l'exécuter. Si vous faites cela, vous pouvez également le déboguer plus facilement car il y a une source réelle pour le débogueur à afficher. Voir aussi l'article de Malte Borchs dans le numéro de juillet du magazine Python, où il parle entre autres choses.

1

Mise à jour pour Python3 - il y a aussi un assembleur très intéressant zachariahreed/byteasm.

En fait, le seul qui travaille pour moi dans Py3. Il a très bien & API propre:

>>> 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)