Python-Modul mit ast parsen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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. :)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
BlackJack

@snafu: Das geht nicht weil der Code auf Modulebene nach dem importieren sofort "weggeworfen" wird. Der wird ja nicht mehr benötigt.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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...
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
Antworten