2009-08-08 10 views
1

Python n'est pas un très bon langage en définissant un ensemble de commandes à exécuter. Bash est. Mais Bash ne fonctionne pas naïvement sur Windows. Contexte: J'essaye de construire un ensemble de programmes - avec des relations de dépendance établies entre eux - sur mac/win/linux. Quelque chose comme macports, mais devrait fonctionner sur toutes les trois plates-formes énumérées.Syntaxe d'exécution de commande portable implémentée en Python

Cela engendre le besoin d'avoir un langage de coquille qui peut être utilisé pour définir la séquence de commande pour exécuter pour la construction/ragréage/etc .. un programme particulier, par exemple:

post-destroot { 
    xinstall -d ${destroot}${prefix}/share/emacs/${version}/leim 
    delete ${destroot}${prefix}/bin/ctags 
    delete ${destroot}${prefix}/share/man/man1/ctags.1 
    if {[variant_isset carbon]} { 
     global version 
     delete ${destroot}${prefix}/bin/emacs ${destroot}${prefix}/bin/emacs-${version} 
    } 
} 

Ce qui précède provient du emacs Portfile in macports. Notez l'utilisation de variables, de conditions, de fonctions .. en plus de spécifier une simple liste de commandes à exécuter dans cet ordre.

Bien que la syntaxe ne soit pas Python, la sémantique d'exécution réelle doit être différée vers Python en utilisant un sous-processus ou autre. En résumé, je devrais être capable de 'lancer' un tel script .. mais pour chaque commande une fonction de hook spécifiée est appelée qui exécute réellement n'importe quelle commande passée en argument. J'espère que vous avez l'idée.

+0

Que demandez-vous ici? Des conseils sur le design? Un extrait de code? S'il vous plaît soyez plus précis. – Pinochle

+0

Je ne demande pas d'extrait de code; mais des idées sur la façon dont un tel interpréteur de commande peut être implémenté ou réutilisé (il semble que macports utilise Tcl) –

Répondre

2

On dirait que vous avez besoin d'une combinaison de PyParsing et Python Subprocess.

Je trouve le sous-processus un peu confus, malgré le MOTW à ce sujet, alors j'utilise beaucoup ce type de code d'emballage.

from subprocess import Popen, PIPE 

def shell(args, input=None): 
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) 
    stdout, stderr = p.communicate(input=input) 
    return stdout, stderr 
1

Ned Batchelder, en this post, énumère plusieurs dizaines de différents outils que vous pouvez choisir d'effectuer l'analyse syntaxique, en Python, d'un langage arbitraire (bien que je ne comprends pas bien pourquoi vous ne voulez pas utiliser Python lui-même comme votre "langage pour définir un ensemble de commandes à exécuter", je suis sûr que vous avez vos propres raisons). Un de ces outils Ned est en train de pyper, comme le mentionne Gregg, mais il y en a plus de trente autres donc vous voudrez peut-être jeter un coup d'œil avant de choisir celui qui vous convient le mieux. Une fois que vous avez transformé votre langage source en un arbre de syntaxe ou une autre représentation pratique en mémoire, vous pouvez simplement parcourir l'arbre et l'exécuter au fur et à mesure (insertion de valeurs variables, branchements sur conditionnels et boucles, etc.). Outre la possibilité d'exécuter des processus externes (par exemple via un sous-processus, que ce soit suggéré par Gregg ou non), n'oubliez pas que Python lui-même peut exécuter certaines de vos commandes élémentaires sans trop de sueur et, si possible, ce qui sera nettement plus rapide que de déléguer l'exécution à un processus enfant (en effet, une des premières motivations du succès de Perl était qu'il pouvait faire beaucoup de choses dans un processus, alors que sh perdait comme un fou, descendants modernes de sh comme bash et ksh a pris la leçon, et maintenant mettre en œuvre un grand nombre de built-ins qui peuvent s'exécuter dans le même processus que le script principal ;-). Par exemple, cette commande delete dans votre exemple peut être implémentée "en interne" via os.unlink (impossible de lier les docs en ligne Python pour le moment car python.org est actuellement arrêté en raison de problèmes HW ;-).

0

Voilà ma suggestion trivial: parse via regexp à Python il devient

def post_destroot(): 
    xinstall ('-d', '${destroot}${prefix}/share/emacs/${version}/leim') 
    delete ('${destroot}${prefix}/bin/ctags') 
    delete ('${destroot}${prefix}/share/man/man1/ctags.1') 
    if test('variant_isset', 'carbon'): 
     global('version') 
     delete('${destroot}${prefix}/bin/emacs', '${destroot}${prefix}/bin/emacs-${version}') 

Je pense que ce n'est pas difficile d'écrire xinstall(), delete() et test() fonctions, d'autant plus que Python a déjà intégré la fonction au format cordes "{destroot}".format(dictionary).

Mais pourquoi s'embêter? Essayez de regarder dans le module distutils de la bibliothèque standard.

+0

Le code distutils est moche comme l'enfer. –

Questions connexes