Hi,
durch einen anderen Beitrag hier bin ich gerade auf das neue (ab Version 2.6) Modul `ast` gestoßen. Weiß jemand, ob man damit auch andere Module/py-Dateien bzw. generell Python-Objekte (z.B. Klassen) parsen kann?
Es gibt zwar die Funktion parse(), aber die parst anscheinend keine Objekte, sondern Ausdrücke.
Kann auch sein, dass ich etwas in der Doku übersehe. Dann wäre ich für einen Hinweis dankbar.
Python-Modul mit ast parsen
Du übersiehst was... Der Parameter `mode` sagt, ob es ein Ausdruck, eine Anweisungsfolge oder eine einzelne Anweisung ist. Bessere wäre gewesen, hätte man den ersten Parameter nicht `expr` genannt, sondern `source`, wie in der Hilfe der `compile`-Funktion.
Stefan
Code: Alles auswählen
module = ast.parse("""for i in range(10): print i""")
print ast.dump(module)
Jaja, so habe ich das schon verstanden. Ich meinte jetzt eher:
Und dann hätte ich idealerweise Zugriff auf den kompletten Baum des Moduls.
Hintergrund ist: Ich möchte die settings.py von Django-Projekten parsen. Bisher mache ich das über eine modifizierte Dictionary-Klasse: http://paste.pocoo.org/show/126732/
Jetzt, wo ich auf `ast` gestoßen bin, fände ich es irgendwie sauberer, im Baum die Namen rauszusuchen. Zudem könnte ich dann auch die Einstellungen einfacher in die Datei zurückschreiben und die alte Struktur (die ganzen Kommentare und die Anordnung) bliebe erhalten, ohne dass man sich mit Templates, regulären Ausdrücken oder was auch immer verrenken müsste. Überhaupt würde es vieles vereinfachen, wenn ich die Struktur kenne, anstatt das stumpf in nem Dict anzuzeigen. Und bei `ast` habe ich wie gesagt gehofft, dass es mir etwas Arbeit abnimmt.
Code: Alles auswählen
import foo
print ast.dump(foo)
Hintergrund ist: Ich möchte die settings.py von Django-Projekten parsen. Bisher mache ich das über eine modifizierte Dictionary-Klasse: http://paste.pocoo.org/show/126732/
Jetzt, wo ich auf `ast` gestoßen bin, fände ich es irgendwie sauberer, im Baum die Namen rauszusuchen. Zudem könnte ich dann auch die Einstellungen einfacher in die Datei zurückschreiben und die alte Struktur (die ganzen Kommentare und die Anordnung) bliebe erhalten, ohne dass man sich mit Templates, regulären Ausdrücken oder was auch immer verrenken müsste. Überhaupt würde es vieles vereinfachen, wenn ich die Struktur kenne, anstatt das stumpf in nem Dict anzuzeigen. Und bei `ast` habe ich wie gesagt gehofft, dass es mir etwas Arbeit abnimmt.
@snafu: Das geht nicht weil der Code auf Modulebene nach dem importieren sofort "weggeworfen" wird. Der wird ja nicht mehr benötigt.
Gäbe es Alternativen für mein Vorhaben? Eben außer den Sachen, die ich schon genannt habe?
EDIT: Achso, oder ich evaluiere den gesamten Modulcode und dann hat man ja den Baum.
Aber es gibt ja auch [mod]inspect[/mod]. Ich gucke da gerade...
EDIT: Achso, oder ich evaluiere den gesamten Modulcode und dann hat man ja den Baum.
Aber es gibt ja auch [mod]inspect[/mod]. Ich gucke da gerade...
Hm, bei `inspect` sehe ich auch keine einfache Möglichkeit, an die Namen zu kommen. Und getcomments() spuckt überhaupt nichts aus. Aber ich glaube, das macht auch nicht wirklich, was ich will.
Was ich gerade gesagt hab, funktioniert übrigens: Einfach den Inhalt der Moduldatei an `ast.parse()` übergeben.
Was ich gerade gesagt hab, funktioniert übrigens: Einfach den Inhalt der Moduldatei an `ast.parse()` übergeben.
Das Modul weiß doch, wo es herkommt. Wenn man hofft, dass man nicht nur eine pyc-Datei hat, sondern auch noch die py-Datei, geht doch folgendes:
Stefan
Code: Alles auswählen
import ast
def parse_module(m):
f = m.__file__
if f.endswith("pyc"): f = f[:-1]
return ast.parse(open(f).read())
print ast.dump(parse_module(ast))
Naja, ich werde es wohl eher so machen, dass als Argument der Pfad zum Modul erwartet wird. Es wäre unnötig komliziert, wenn der spätere Benutzer erst das Modul importieren muss (es muss ja überhaupt erstmal das im richtigen Projektverzeichnis angesprochen werden), nur damit er es danach an den Parser übergibt und sonst nichts davon hat.
Das ast-Modul ignoriert anscheinend Kommentare und Leerzeilen. Der einzige Vorteil gegenüber meiner Variante mit `dir()` wäre, dass ich auf jeden Fall nur Namen bekommen kann (also ohne testen auf Unterstriche), weil es dafür eben einen bestimmten Typen gibt.
Da hab ich mir jetzt aber eigentlich mehr erhofft. Aber verstehen kann ich's: Kommentare und Leerzeilen werden halt nicht von Python gebraucht.
Da hab ich mir jetzt aber eigentlich mehr erhofft. Aber verstehen kann ich's: Kommentare und Leerzeilen werden halt nicht von Python gebraucht.