os.system Rückgaben verarbeiten

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
HL
User
Beiträge: 14
Registriert: Donnerstag 20. März 2008, 01:05
Kontaktdaten:

Donnerstag 27. März 2008, 19:05

Hallo Forum,

Ich möchte bestimmte Dateien anhand eines Musters finden und diese dann Datei für Datei weiter verarbeiten.

Code: Alles auswählen

os.system('find . -type f -print0 | xargs -0 grep Muster')
Aber wie bekomme ich die einzelnen Zeilen der Konsolen Ausgabe in eine Liste?
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Donnerstag 27. März 2008, 19:18

`[mod]subprocess[/mod].Popen` verwenden und über das `stdout`-Attribut des `Popen`-Objekts iterieren.

Oder die Funktionalität des aufgerufenen Befehls einfach in Python nachbauen, das `[mod]os[/mod]`-Modul hat da interessante Funktionen.
lunar

Donnerstag 27. März 2008, 22:49

Der gezeigte Code ist ziemlich schlecht. Zum einen verlässt du dich damit darauf, dass /bin/sh tatsächlich auf eine POSIX-Shell zeigt, was nicht immer der Fall ist. Manche C-Shells, die auf diversen Unixen unter /bin/sh verlinkt sind, haben mitunter eine merkwürdige Auffassung von POSIX. Außerdem sind die Argument -print0 und -0 nicht POSIX-kompatibel, außerhalb des GNU-Raums läuft der Code also nicht.

Zudem scheint es, als wäre "MUSTER" eine Benutzereingabe. In diesem Fall ist jegliche Art von Aufruf über eine Subshell - sei es nun über system oder über subprocess mit shell=True - falsch, da man so Shell Injection und Bugs Tür und Tor öffnet.

Grundsätzlich sollte man immer auf subprocess zurückgreifen, und das Aufrufen von SH-Code in Python-Skripten immer vermeiden!
Benutzeravatar
HL
User
Beiträge: 14
Registriert: Donnerstag 20. März 2008, 01:05
Kontaktdaten:

Freitag 28. März 2008, 08:24

Danke für den Tipp, dass subprocess die "schöne" Art ist zu meiner Lösung zu kommen. Werde ich mir mal zu Gemüte führen.

@lunar: Ich hatte nicht erwähnt, das dies ein Administrationsskript werden soll, welches nur auf zwei hausinternen Servern seine Arbeit verrichten soll.
Da ich dort viele Verzeichnisse mit vielen Datein durchsuchen will, bin ich bisher mit dem gezeigten Shellkommando gut zurecht gekommen - alle anderen Versuche warfen mir ein "too many arguments" um die Ohren.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Freitag 28. März 2008, 09:40

Zumindest GNU grep kennt ``-r`` für rekursives Durchsuchen von Verzeichnissen.
lunar

Freitag 28. März 2008, 16:33

Trundle hat geschrieben:Zumindest GNU grep kennt ``-r`` für rekursives Durchsuchen von Verzeichnissen.
Ob das Aufrufen von externen Shell-Kommandos da wirklich der richtige Weg ist, bezweifele ich trotzdem. Wenn man das Admin-Skript in Python schreibt, dann sollte man auch bei Python bleiben, wenn es irgend geht.

Zumal das gezeigte Shell-Snippet relativ einfach in Python implementiert werden kann:

Code: Alles auswählen

def grep_recursive(directory, pattern):
    for root, dirnames, filenames in os.walk(directory):
        for filename in filenames:
            filename = os.path.join(root, filename)
            with open(filename) as stream:
                for lineno, line in enumerate(stream):
                    if pattern in line:
                        yield filename, lineno+1, line
Mit path.py sogar noch einfacher:

Code: Alles auswählen

def grep_recursive(directory, pattern):
    for filename in path(directory).walkfiles():
        with open(filename) as stream:
            for lineno, line in enumerate(stream):
                if pattern in line:
                    yield filename, lineno+1, line
Insofern sehe ich gerade nicht wirklich Sinn dahinter, grep und find aus Python heraus aufzurufen.

Edit: Funktionen verbessert.
Zuletzt geändert von lunar am Freitag 28. März 2008, 16:48, insgesamt 1-mal geändert.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Freitag 28. März 2008, 16:44

lunar hat geschrieben:
Trundle hat geschrieben:Zumindest GNU grep kennt ``-r`` für rekursives Durchsuchen von Verzeichnissen.
Ob das Aufrufen von externen Shell-Kommandos da wirklich der richtige Weg ist, bezweifele ich trotzdem. Wenn man das Admin-Skript in Python schreibt, dann sollte man auch bei Python bleiben, wenn es irgend geht.
Ich denke auch, dass es schöner ist, das komplett in Python zu schreiben, wenn man eh schon einen Teil davon in Python schreibt. War eher als allgemeine Feststellung zu ``too many arguments`` gedacht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Freitag 28. März 2008, 17:19

Aber für regexps müsste man die Funktionen noch erweitern! Bei grep funzen die auch so schon ;-)

Na klar mag man vieles direkt in Python machen können, es ist nur die Frage, ob man sich da 1.) sicher genug drin fühlt und 2.) was schneller geht und 3.) was auch wirklich funktioniert. bei einem grep bin ich da recht sicher, da es zig Milleionen mal am Tag genutzt wird - bei einer eigenen Fumktion bin ich das sicherlich nicht!

Generell wäre ich aber auch der Auffassung, die Shell nur da einzusetzen, wo ich mit Python wirklich nicht sinnvoll weiterkomme!
lunar

Freitag 28. März 2008, 19:47

Hyperion hat geschrieben:Aber für regexps müsste man die Funktionen noch erweitern! Bei grep funzen die auch so schon ;-)

Code: Alles auswählen

def grep_recursive(directory, pattern):
    matches = (lambda s: pattern in s
               if isinstance(pattern, basestring) else pattern.search)
    for filename in path(directory).walkfiles():
        with open(filename) as stream:
            for lineno, line in enumerate(stream):
                if matches(line):
                    yield filename, lineno+1, line
Na klar mag man vieles direkt in Python machen können, es ist nur die Frage, ob man sich da 1.) sicher genug drin fühlt und 2.) was schneller geht und 3.) was auch wirklich funktioniert. bei einem grep bin ich da recht sicher, da es zig Milleionen mal am Tag genutzt wird - bei einer eigenen Fumktion bin ich das sicherlich nicht!
zu 1.): Übung macht den Meister ;)
zu 2.): timeit ;) Allerdings dürfte der Unterschied imho nicht groß sein, zumindest bei deinem Snippet. Das ruft nämlich für jede einzelne Datei grep auf, was ziemlich auf die Performance schlägt. grep -R müsste man wirklich testen, an große Geschwindigkeitsunterschiede glaube ich aber nicht.
zu 3.) Was soll ich sagen... man muss sich schon sehr schwer tun, um rekursives Suchen in Dateien wirklich zu versauen ;)
Antworten