2009-02-25 20 views
7

Me gustaría enumerar todas las cadenas dentro de mi proyecto python grande.Buscar todas las cadenas en los archivos de código python

imaginar las diferentes posibilidades para crear una cadena en Python:

mystring = "hello world" 

mystring = ("hello " 
      "world") 

mystring = "hello " \ 
      "world" 

Necesito una herramienta que da salida a "nombre de archivo, LineNumber, cadena" para cada cuerda en mi proyecto. Las cadenas que se extienden en varias líneas con "\" o "('')" deben mostrarse en una sola línea.

¿Alguna idea de cómo se podría hacer esto?

+0

si la intención de actuar sobre la información: "nombre de archivo, LineNumber, cadena" a continuación biblioteca lib2to3 de stdlib podría darle algunas ideas sobre cómo refactorizar código Python a gran escala, especialmente de archivos refactor.py lib2to3 /. Puede que solo necesite escribir su propio accesorio y ya está. – jfs

Respuesta

3

Si puede hacer esto en Python, le sugiero que comience por mirar el módulo ast (Árbol de sintaxis abstracta), y vaya desde allí.

0

Gettext podría ayudarle. Ponga sus cadenas en _(...) estructuras:

a = _('Test') 
b = a 
c = _('Another text') 

A continuación, ejecute en el intérprete de comandos:

pygettext test.py 

que obtendrá un archivo messages.pot con la información que necesita:

# SOME DESCRIPTIVE TITLE. 
# Copyright (C) YEAR ORGANIZATION 
# FIRST AUTHOR <[email protected]>, YEAR. 
# 
msgid "" 
msgstr "" 
"Project-Id-Version: PACKAGE VERSION\n" 
"POT-Creation-Date: 2009-02-25 08:48+BRT\n" 
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 
"Last-Translator: FULL NAME <[email protected]>\n" 
"Language-Team: LANGUAGE <[email protected]>\n" 
"MIME-Version: 1.0\n" 
"Content-Type: text/plain; charset=CHARSET\n" 
"Content-Transfer-Encoding: ENCODING\n" 
"Generated-By: pygettext.py 1.5\n" 


#: teste.py:1 
msgid "Test" 
msgstr "" 

#: teste.py:3 
msgid "Another text" 
msgstr "" 
+0

Creo que están tratando de encontrar las cadenas para que puedan poner las _() 's alrededor de ellas. –

2

También puede considerar analizar su código con pygments.

no sé la otra solución, pero seguro que es muy sencillo de utilizar .

11

Desenrollar la sugerencia de utilizar el módulo ast en 2.6 es una buena idea. (También hay el módulo _ast indocumentado en 2.5.) Aquí es código de ejemplo para que

code = """a = 'blah' 
b = '''multi 
line 
string''' 
c = u"spam" 
""" 

import ast 
root = ast.parse(code) 

class ShowStrings(ast.NodeVisitor): 
    def visit_Str(self, node): 
    print "string at", node.lineno, node.col_offset, repr(node.s) 

show_strings = ShowStrings() 
show_strings.visit(root) 

El problema es líneas múltiples. Si ejecuta lo anterior, obtendrá.

string at 1 4 'blah' 
string at 4 -1 'multi\nline\nstring' 
string at 5 4 u'spam' 

Verá que no informa el comienzo de la cadena de varias líneas, solo el final. No hay una buena solución para eso usando las herramientas integradas de Python.

Otra opción es que puede usar mi módulo 'python4ply'. Esta es una definición de gramática para Python para PLY, que es un generador de analizador sintáctico.He aquí cómo usted puede utilizarlo:

import compiler 
import compiler.visitor 

# from python4ply; requires the ply parser generator 
import python_yacc 

code = """a = 'blah' 
b = '''multi 
line 
string''' 
c = u"spam" 
d = 1 
""" 

tree = python_yacc.parse(code, "<string>") 
#print tree 

class ShowStrings(compiler.visitor.ASTVisitor): 
    def visitConst(self, node): 
     if isinstance(node.value, basestring): 
      print "string at", node.lineno, repr(node.value) 

visitor = ShowStrings() 
compiler.walk(tree, visitor) 

El resultado de esto es

string at 1 'blah' 
string at 2 'multi\nline\nstring' 
string at 5 u'spam' 

No hay soporte para la información de la columna. (Hay un código comentado en su mayoría completo para apoyar eso, pero no está completamente probado). De nuevo, veo que no lo necesita. También significa trabajar con el módulo 'compilador' de Python, que es más torpe que el módulo AST.

Aún así, con 30-40 líneas de código debe tener exactamente lo que desea.

+0

Esas 30-40 líneas de código, por supuesto, principalmente el código para recorrer su proyecto para encontrar sus archivos de Python. –

+0

¡Eso parece muy prometedor! Probaré tu primera sugerencia (no necesito ninguna información de columna). Si funciona como espero, publicaré la solución final aquí ... – mbrochh

6

Python incluido tokenize módulo también hará el truco.

from __future__ import with_statement 
import sys 
import tokenize 

for filename in sys.argv[1:]: 
    with open(filename) as f: 
     for toktype, tokstr, (lineno, _), _, _ in tokenize.generate_tokens(f.readline): 
      if toktype == tokenize.STRING: 
       strrepr = repr(eval(tokstr)) 
       print filename, lineno, strrepr 
+0

¡Agradable! Más simple y más directo que las soluciones basadas en el analizador, como la que hice. +1 –

Cuestiones relacionadas