Kommando mit ">" ausführen

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
bronkopavel
User
Beiträge: 4
Registriert: Mittwoch 9. Dezember 2009, 21:39

Mein erster Python "Showstopper":
ich will folgendes ausführen:

Code: Alles auswählen

cmd = "avr-nm -n file.elf > file.sym"

file = open("file.sym", "w")
file.close()

process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
stdout = process.communicate()[0]
print stdout
Leider wird mit dem > Operator auf die Kommandozeile redirektet und nicht in die Datei. file.elf existiert natürlich. Was mache ich falsch?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

bronkopavel hat geschrieben:Was mache ich falsch?
Du verwechselst Python mit ner Shell?
Das clobbing ist ein Feature der Shells und hat primaer nichts mit dem Prozess zu tun, evtl. geht es, wenn du eine Shell dazwischenschaltest (`shell=True`), aber der saubere Weg ist, das selbst zu uebernehmen.

Dein Command-Handling ist btw recht fahrlaessig.
Ungetestet:

Code: Alles auswählen

cmd = ["avr-nm", "-n", "file.elf"]

with open("file.sym", "w") as fobj:
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    fobj.write(process.communicate()[0])
bronkopavel
User
Beiträge: 4
Registriert: Mittwoch 9. Dezember 2009, 21:39

Danke, es funktioniert!
Dein Command-Handling ist btw recht fahrlaessig.
Ich habe die Zeilen

Code: Alles auswählen

process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
stdout = process.communicate()[0]
print stdout
aus dem Netz und bin Pythonanfänger. Ist das mit split() nicht so gut?Warum?
Das mit "with" kenne ich noch nicht, werde es aber noch nachlesen.
Btw. ich versuche einen maker für den avr-gcc zu schreiben und möchte mittels threading alle compiler aufrufe "parallel" starten. Ich weiß nur, das ich das modul threading verwenden werde, vielleicht kennst du hier ein Beispiel wie ich:
1. mehrere threads starten (compilieren)
2. warten bis alle fertig sind bzw. abfangen wenn Fehler passiert sind
3. linken

Gruß
Bronko
fhoech
User
Beiträge: 143
Registriert: Montag 9. April 2007, 18:26

Einen Einzeiler hätte ich noch :)

Code: Alles auswählen

returncode = subprocess.call(["avr-nm", "-n", "file.elf"], stdout=open("file.sym", "w"))
BlackJack

@bronkopavel: Das mit dem `split()` funktioniert zum Beispiel nicht mehr, wenn in einem der Argumente ein Leerzeichen vorkommt.

Wenn Du in Deinem Programm die Ausgaben nicht verarbeitest, kommst Du auch ohne Threads aus, weil die Prozesse ja grundsätzlich auch asynchron gestartet werden.

@fhoech: Da wird die Datei aber nicht mehr explizit geschlossen und wenn man das mit oft macht, können einem die Dateihandles ausgehen, wenn der Garbage Collector nicht hinterherkommt. Und nein, dass das vermutlich bei der aktuellen CPython-Implementierung nicht passieren wird, ist IMHO kein Argument.
bronkopavel
User
Beiträge: 4
Registriert: Mittwoch 9. Dezember 2009, 21:39

Danke für die Antworten, das mit split() hab ich kapiert, werde jetzt wohl eine Liste für die Argumente nehmen. Bei mir ist das gegangen (Zufallsprodukt).

@BlackJack: Du hast recht, dass ich eigentlich keine threads brauche, jedoch weiß ich nicht, wie ich dann weiß, wann alle Compilervoränge beendet sind (damit ich mit dem Linken usw. starten kann). Der Output des Compiler auf der Kommandozeile reicht, ein Abfangen und Weiterverarbeiten ist nicht notwendig. Der Output der Vorgänge sollte aber nicht verschachtelt ausgegeben werden.
Da die Anzahl der (parallelen) Compilervorgänge bekannt ist, könnte ich evtl eine (globale) Variable runterzählen oder geht das auch eleganter mit einer queue (da könnte man poppen :lol:)?
Ziel ist es das das ganze möglich schnell läuft (später werde ich evtl. noch die Anzahl der Prozessoren/Compilervorgänge berücksichtigen)
BlackJack

@bronkopavel: Wenn sich die Ausgabe der parallel gestarteten Prozesse nicht vermischen soll, dann musst Du sie doch selber im Skript sammeln und kontrolliert nacheinander ausgeben. Sonst kann man das nicht garantieren. Also doch Threads. :-)

Threads haben eine `join()`-Methode und bei `subprocess.Popen`-Exemplaren blockiert die `communicate()`-Methode ja so lange bis der Prozess fertig ist.
bronkopavel
User
Beiträge: 4
Registriert: Mittwoch 9. Dezember 2009, 21:39

Ich schaffe es einfach nicht den .o.g. string als Teil meines Programmaufrufs mit den Anführungszeichen auszugeben:

Code: Alles auswählen

cmdLine = list()   
cmdLine.append(r'--set-section-flags=.eeprom="alloc,load"')
print cmdLine
print "REAL CMD LINE: ", subprocess.list2cmdline(cmdLine)
Das kommt dabei raus:
['--set-section-flags=.eeprom="alloc,load"']
REAL CMD LINE: --set-section-flags=.eeprom=\"alloc,load\"
Warum ist der String in der Liste plötzlich mit zwei \ ??
[/quote]
Antworten