Seite 1 von 1

Python-Modul mit ast parsen

Verfasst: Sonntag 5. Juli 2009, 07:22
von snafu
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. :)

Verfasst: Sonntag 5. Juli 2009, 08:08
von sma
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.

Code: Alles auswählen

module = ast.parse("""for i in range(10): print i""")
print ast.dump(module)
Stefan

Verfasst: Sonntag 5. Juli 2009, 08:39
von snafu
Jaja, so habe ich das schon verstanden. Ich meinte jetzt eher:

Code: Alles auswählen

import foo
print ast.dump(foo)
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.

Verfasst: Sonntag 5. Juli 2009, 09:16
von BlackJack
@snafu: Das geht nicht weil der Code auf Modulebene nach dem importieren sofort "weggeworfen" wird. Der wird ja nicht mehr benötigt.

Verfasst: Sonntag 5. Juli 2009, 09:23
von snafu
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...

Verfasst: Sonntag 5. Juli 2009, 09:40
von snafu
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.

Verfasst: Sonntag 5. Juli 2009, 10:00
von sma
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:

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))
Stefan

Verfasst: Sonntag 5. Juli 2009, 10:07
von snafu
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.

Verfasst: Sonntag 5. Juli 2009, 11:06
von snafu
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.