2009-02-25 27 views
7

Chciałbym wyświetlić wszystkie ciągi w ramach mojego dużego projektu python.Znajdź wszystkie ciągi w plikach kodu Pythona

Wyobraźmy sobie różne możliwości, aby utworzyć ciąg w Pythonie:

mystring = "hello world" 

mystring = ("hello " 
      "world") 

mystring = "hello " \ 
      "world" 

muszę narzędzie, które Wyjścia „nazwa_pliku, LineNumber, łańcuch” dla każdej struny w moim projekcie. Ciągi, które są rozłożone na wiele linii za pomocą "\" lub "(" ")" powinny być wyświetlane w jednym wierszu.

Jakieś pomysły, jak to zrobić?

+0

jeśli zamiar działać na informacjach: „nazwy pliku, LineNumber, string”, a następnie lib2to3 biblioteka stdlib za może dać ci kilka pomysłów na to, jak byłaby kodu Pythona na dużą skalę, zwłaszcza lib2to3/refactor.py pliku. Być może wystarczy tylko napisać dla niego własne urządzenie i gotowe. – jfs

Odpowiedz

3

Jeśli możesz to zrobić w Pythonie, proponuję zacząć od spojrzenia na moduł ast (drzewo składni abstrakcyjnych) i wychodząc z niego.

0

Gettext może pomóc. Umieść swoje struny w _(...) struktur:

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

Następnie należy uruchomić w wierszu powłoki:

pygettext test.py 

Dostaniesz plik messages.pot z informacjami trzeba:

# 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

Sądzę, że próbują znaleźć ciągi znaków, aby mogły umieścić wokół nich _(). –

2

Możesz również rozważyć przeanalizowanie kodu za pomocą pygments.

Nie znam innego rozwiązania, ale z pewnością jest bardzo łatwe w użyciu.

11

Sugerowana przez unwind sugestia użycia modułu ast w wersji 2.6 jest bardzo dobra. (Jest też nieudokumentowane moduł _ast w 2.5.) Oto przykładowy kod dla tej

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) 

Problem polega na multilinii struny. Jeśli uruchomisz powyższe, dostaniesz.

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

Widzisz, że nie zgłasza początku ciągu wielowierszowego, tylko koniec. Nie ma na to dobrego rozwiązania za pomocą wbudowanych narzędzi Pythona.

Inną opcją jest możliwość korzystania z mojego modułu "python4ply". To jest definicja gramatyki dla Pythona dla PLY, która jest generatorem analizatora składni.Oto w jaki sposób można go używać:

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) 

Wyjście z tego jest

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

Nie ma wsparcia dla kolumny informacji. (Jest tam w większości kompletny skomentowany kod, ale nie jest w pełni przetestowany.) Potem znowu widzę, że go nie potrzebujesz. Oznacza to również pracę z modułem "kompilatora" Pythona, który jest bardziej złożony niż moduł AST.

Mimo to, z 30-40 liniami kodu, powinieneś mieć dokładnie to, co chcesz.

+0

Te 30-40 linii kodu, oczywiście, to głównie kod do przechodzenia przez twój projekt, aby znaleźć pliki Pythona. –

+0

To wygląda bardzo obiecująco! Spróbuję twojej pierwszej sugestii (nie potrzebuję żadnych informacji o kolumnie). Jeśli to działa, mam nadzieję, że zamieszczę tutaj ostateczne rozwiązanie ... – mbrochh

6

Dołączony moduł Pythona tokenize również będzie działał.

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

Miło! Prostsze i bardziej bezpośrednie niż rozwiązania oparte na analizatorach składni, takie jak te, które zrobiłem. +1 –