2010-06-18 6 views
1

Je voudrais écrire un programme qui modifient les programmes de python ainsi:Puis-je utiliser python ast module pour cela?

changement

"une chaîne littérale%" % CHOSE

à

functioncall ("une chaîne littérale % ")% CHOSE

Merci,

+0

Vous pourriez avoir plus de chance en utilisant l'outil 2to3, qui est conçu pour les transformations source-à-source. –

Répondre

1

Vous pouvez résoudre ce d'avoir à écrire un programme. Au lieu de cela, utilisez simplement le meilleur éditeur jamais créé: Emacs. Ça vaut le coup d'apprendre si vous ne l'avez pas déjà fait. Avec cela, vous pouvez résoudre cela en utilisant sa capacité regex-replace. Le seul problème est que j'utilise rarement les regex, donc j'oublie toujours les détails de la syntaxe énigmatique et je dois toujours le chercher: P Je vais essayer de le comprendre à nouveau pour vous. Voici un lien vers la Search & Replace Info for Emacs - scroll down for using regex's

+1

J'ai besoin d'un moyen de le faire de façon mélodramatique, donc je peux l'inclure dans un autre programme comme une sorte de préprocesseur. –

+0

[Melodrama] (http://en.wikipedia.org/wiki/Melodrama) tiquement, hein? Mais si vous voulez faire du code, utilisez le module 're' de python pour gérer les expressions régulières. – JAB

+0

Mélodramatiquement j'ai tapé? F * vérificateur d'orthographe. J'étais programmé. –

2

Il peut être plus simple avec tokenize - adapter l'exemple dans la documentation,

import cStringIO 
import tokenize 

class Lookahead(object): 

    def __init__(self, s): 
    self._t = tokenize.generate_tokens(cStringIO.StringIO(s).readline) 
    self.lookahead = next(self._t, None) 

    def __iter__(self): 
    return self 

    def next(self): 
    result = self.lookahead 
    if result is None: raise StopIteration 
    self.lookahead = next(self._t, None) 
    return result 


def doit(s): 
    toks = Lookahead(s) 
    result = [] 
    for toktype, tokvalue, _, _, _ in toks: 
    if toktype == tokenize.STRING: 
     pk = toks.lookahead 
     if pk is not None and pk[0] == tokenize.OP and pk[1] == '%': 
     result.extend([ 
      (tokenize.NAME, 'functioncall'), 
      (tokenize.OP, '('), 
      (tokenize.STRING, repr(tokvalue)), 
      (tokenize.OP, ')') 
     ]) 
     continue 
    result.append((toktype, tokvalue)) 
    return tokenize.untokenize(result) 


print doit('"some literal string %" % SOMETHING') 

Imprime functioncall ('"some literal string %"')%SOMETHING. L'espacement est assez particulier (il faut beaucoup plus d'efforts pour obtenir l'espacement juste - mais c'est encore pire pour reconstruire des sources à partir d'un AST modifié), mais ça va bien si tout ce que vous allez faire est d'importer/exécuter le code résultant (pas si bien si vous voulez obtenir un code lisible et modifiable - mais c'est un assez gros problème que je suggère un Q séparé ;-).

+0

Il semble y avoir des citations non désirées par rapport à ce que le PO demandait.Je crois que remplacer repr (tokvalue) par tokvalue donne le résultat désiré. –

0

Here est une autre question SO qui peut être utile.

Je suppose que le module ast ne dispose pas d'un établissement pour revenir au code source, mais Armin Ronacher a écrit un module codegen qui met en œuvre une fonction to_source pour faire juste que pour ast nœuds.

Je n'ai pas essayé de le faire moi-même.

+0

Le module codegen ne fonctionne pas pour chaque code python :( –

0
import re 

pattern = r'(".+? %")(?= %)' 
oldstr = '"some literal string %" % SOMETHING' 

newstr = re.sub(pattern, r'functioncall(\1)', oldstr) 

Essayez quelque chose comme ça. (Bien qu'avec le fichier I/O, bien sûr.) Je n'ai pas encore travaillé avec ast, donc je ne sais pas si l'utiliser serait plus facile pour quelque chose comme ça, mais il me semble que si vous faites juste une simple recherche-remplacer et ne faites pas vraiment beaucoup d'analyse complexe alors il n'y a pas besoin d'utiliser ast.