Seite 1 von 1

Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Donnerstag 11. August 2011, 12:54
von handle
Subprocess.Popen, eine Win32 Anwendung und ein Argument in Anführungszeichen unter Windows mit Python 3.2.

Code: Alles auswählen

try:
	retcode = subprocess.Popen( [ r"my.exe \"{}\"".format( "filename.ext" ) ], shell=True ).communicate()[0]
	print( retcode )
except WindowsError as e:
	print( e )
verursacht den Fehler "Das System kann den angegebenen Pfad nicht finden." Das ist das Verhalten der Anwendung, wenn der Dateiname nicht in Anführungszeichen übergeben wird (manuell).
Unter Windows verwendet Subprocess.Popen eine Methode, um eine Liste der Argumente in einen String umzuwandeln: print( subprocess.list2cmdline( params ) )
Das gibt etwas wie "my.exe \"filename.ext\""

Die Option shell=True bewirkt unterschiedliche Fehlermeldungen (ohne: "[Error 2] Das System...") der Anwendung, die eigentlich im Fehlerfall ein Dialogfenster öffnet. Vielleicht ist das das Problem, dass es sich nicht um eine echte Konsolenanwendung handelt?

PS: Wenn ich die Argumente als Liste übergebe, ohne shell=True, bewirkt das, dass der Fehler im Dialogfenster kommt.. Es bewirkt auch, dass list2cmdline keine Anführungszeichen um den kompletten Aufruf setzt, dafür ist aber das Argument, dass in Anführungszeichen sein sollte, mit Backslashes escaped (\"argument\") (In der Liste habe ich die Anführungszeichen manuell dem Argument-String hinzugefügt).

Re: Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Donnerstag 11. August 2011, 13:06
von BlackJack
@handle: Das sieht so aus als hättest Du da wild herum probiert. Bei ``shell=True`` sollte man eine Zeichenkette übergeben mit genau der Zeichenkette, die man auch in der Eingabeaufforderung eingeben würde. So wie Du das geschrieben hast (mal die Liste ignorierend), wäre das ``my.exe \"filename.ext\"`` — was sicher nicht funktionieren dürfte wenn der Dateiname nicht tatsächlich mit Anführungsstrichen beginnt und endet.

Wenn Du nicht den Umweg über die Shell nimmst, was empfehlenswert ist, weil man sich dann nicht mit all dem herum schlagen muss, wovor man Werte in einer Kommandozeile schützen muss, dann müssen Programm und Argumente als einzelne Argumente in der Liste stehen! Weil man dann ja das aufteilen der Argumente selber macht, statt das der Shell zu überlassen. Das wäre dann einfach nur ``Popen(['my.exe', 'filename.ext'])``.

Re: Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Donnerstag 11. August 2011, 13:18
von handle
Hallo und Danke - ja, wenn es nicht funktioniert, muss ich ja probieren.
Als Liste scheint es besser zu funktionieren, aber die Ausgabe mit

Code: Alles auswählen

params = ["my.exe", '"file.name"']
print( subprocess.list2cmdline( params ) )
Führt zu

Code: Alles auswählen

my.exe \"file.name\"
und damit zu besagtem Dialogfenster der Anwendung mit der Fehlermeldung.

Wie bekomme ich die Backslashes weg?

Re: Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Donnerstag 11. August 2011, 13:48
von handle
So funktioniert es:

Code: Alles auswählen

retcode = subprocess.Popen( 'my.exe "file.name"', shell=True ).communicate()[0]

Re: Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Donnerstag 11. August 2011, 13:59
von BlackJack
@handle: Die Backslashes sind da um die " for der Shell zu schützen. Wenn Du die " nicht haben willst, dann solltest Du *die* weglassen, statt etwas an den Folgen davon ändern zu wollen.

Re: Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Donnerstag 11. August 2011, 19:54
von handle
BlackJack hat geschrieben:Die Backslashes sind da um die " for der Shell zu schützen.
Der Mechanismus war mir nicht bekannt, aber trotzdem oder deswegen ging es leider nicht. Ich weiß nicht, was die Ursache ist, aber was ich erreichen wollte geht ja jetzt. Also Danke für deine Hilfe!

Re: Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Freitag 12. August 2011, 08:34
von BlackJack
Die Ursache sind wie gesagt die " die *Du* hier reingeschrieben hast, die da nichts zu suchen haben wenn sie nicht tatsächlich Bestandteil des Dateinanmens sind:
handle hat geschrieben:

Code: Alles auswählen

params = ["my.exe", '"file.name"']
print( subprocess.list2cmdline( params ) )
Damit sagst Du das erste Argument für das Programm ist "file.name" was nicht stimmt, weil es tatsächlich nur file.name ist.

Re: Subprocess.Popen, eine Win32 Anwendung und "Argument"

Verfasst: Samstag 13. August 2011, 16:25
von finki
@handle
Was dir einige versuchen zu erklären ist, das wenn du subprocess eine Liste aller Argumente übergibst, dann brauchst du dir nicht die Mühe machen die Leerzeichen zu escapen. Das heißt praktisch keine Anführungszeichen um die Dateinamen schreiben. shell=True gibt an, das du keine Liste benutzen möchtest, sondern die Arbeit selbst in die Hand nimmst und ein String übergeben möchtest, als wenn du in der Kommandozeile sitzen würdest.

Wenn du allerdings eine Liste übergibst, ohne shell=True, dann übernimmt Python den Aufruf für dich und teilt die in der Liste stehenden Argumente auf und macht gegebenenfalls umgebende Anführungszeichen. So das nur mal als Verständnis. Eigentlich hat ja BlackJack das bereits erklärt.

Versuch es mal hiermit:

Code: Alles auswählen

try:
        cmdline = ['my.exe', 'filename.ext']
        retcode = subprocess.Popen(cmdline).communicate()[0]
        print( retcode )
except WindowsError as e:
        print( e )