Seite 1 von 1

os.system Rückgaben verarbeiten

Verfasst: Donnerstag 27. März 2008, 19:05
von HL
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?

Verfasst: Donnerstag 27. März 2008, 19:18
von Trundle
`[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.

Verfasst: Donnerstag 27. März 2008, 22:49
von lunar
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!

Verfasst: Freitag 28. März 2008, 08:24
von HL
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.

Verfasst: Freitag 28. März 2008, 09:40
von Trundle
Zumindest GNU grep kennt ``-r`` für rekursives Durchsuchen von Verzeichnissen.

Verfasst: Freitag 28. März 2008, 16:33
von lunar
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.

Verfasst: Freitag 28. März 2008, 16:44
von Trundle
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.

Verfasst: Freitag 28. März 2008, 17:19
von Hyperion
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!

Verfasst: Freitag 28. März 2008, 19:47
von lunar
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 ;)