Externer Prozess aufrufen - Konsole schließen

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
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo,

mit:

Code: Alles auswählen

import subprocess
subprocess.call('ProgrammPfad file:///D:\...\...\test.ext --repeat')
kann zum Beispiel ein externes Programm mit einer Parameterübergabe gestartet werden.

Das funktioniert einwandfrei, könnte aber, so lange nicht weitere Ansprüche hinzukommen, genau so gut über eine ganz normale Batchdatei erledigt werden.

Meine Frage ist nun, ob der Aufruf so formuliert werden kann, dass der Aufrufprozess unter Python nicht wartet, bis das aufgerufene Programm beendet wird. Das Konsolenfenster sollte unmittelbar nach dem Aufruf schließen. Ist das möglich, wenn ja, wie.

MfG, kodela
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Zum Fenster: http://code.activestate.com/recipes/409 ... le-window/

Zum Warten, schau mal welche Funktionen subprocess noch so hat und was `call` denn genau tut. Daneben: Du benutzt `call` falsch und solltest eine Liste der Argumente uebergeben:

Code: Alles auswählen

subprocess.call(['ProgrammPfad', 'file:///D:\...\...\test.ext', '--repeat'])
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo cofi,

danke für die superschnelle Antwort. Den Aufruf habe ich jetzt einmal nach Deinem Rat durchgeführt. Im Ergebnis hat sich damit aber nichts geändert. Trotzdem glaube ich, dass dies die bessere Lösung ist.

In der von Dir verlinkten Dokumentation habe ich allerdings dieses Beispiel "subprocess.call("mycmd" + " myarg", shell=True)" gefunden. Vom shell-Parameter abgesehen, passiert dort das gleiche, wie in meiner Version. Aufzurufende exe mit den Parametern werden in einem String übergeben.

Dein Link zu den subprocess-Funktionen hat mich auch nicht weiter gebracht. Ich habe dort schon vorher, bevor ich mich an das Forum hier um Hilfe gewandt habe, nach eine entsprechenden Option gesucht, über die das Konsolenfenster sofort nach dem Aufruf geschlossen wird, oder noch besser, erst gar nicht geöffnet, sondern im Hintergrund ausgeführt wird. Einige der gefundenen Optionen habe ich auch ausprobiert, allerdings ohne Erfolg. Da können aber sehr wohl meine fehlenden Englischkenntnisse ursächlich dafür sein.

Besten Erfolg habe ich mit Deinem Link zum Fenster. Ich habe den Code, was die "beweglichen" Daten anbelangt an meine Vorgaben angepasst und in der letzten Zeile von return (Zeile 7) das ".wait()" entfernt. Damit verschwindet das Konsolenfenster, aber ob mit oder ohne dem ".wait()", die GUI des aufgerufenen Programmes (VLC) wird nicht mehr gezeigt. Das im ersten Parameter angegebene Video wird wiedergegeben, der Repeat-Modus (zweiter Parameter) ist auch aktiv, aber man hat nur noch über das Kontextmenü die Möglichkeit, auf die Wiedergabe Einfluss zu nehmen. Das möchte ich eigentlich auch nicht.

Vielleicht gibt es doch noch eine andere Möglichkeit. Für einen kleinen Fingerzeig wäre ich dankbar.

MgG, kodela
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo,

mein Vorhaben kann mit diesen beiden Codezeilen realisiert werden:

Code: Alles auswählen

import subprocess
subprocess.Popen("vlc file:///D:\VLC\Videos\test.mp4 --repeat")
Damit blitzt das Konsolenfenster nur kurz auf. Danach wird das Programm unter Übergabe der angegebenen Parameter gestartet und gibt für diesen Beispielcode ein Video in einer Endlosschleife wieder. Die GUI wird angezeigt.

@cofi:
In dem von Dir zur Fensteranzeige verlinkten Beispiel ist diese Codezeile:

Code: Alles auswählen

return subprocess.Popen([command] + args, startupinfo=startupinfo).wait()
Diese Zeile ähnelt ja sehr meiner Aufrufzeile. Allerdings würde meine Aufrufzeile nicht funktionieren, wenn wie hier im Beispiel der Pfad für das aufzurufende Programm in eckige Klammern gesetzt wäre.

Debugge ich diesen Code, wobei ich hier die Parameter "command" und "args" in Anführungszeichen gesetzt habe, sie stehen ja für Strings, bekomme ich diese Fehlermeldung:

Code: Alles auswählen

>>>s = ["command"] + "args"
Error on CMD
Traceback (most recent call last):
  File "C:\Users\xyz\AppData\Roaming\NetBeans\8.0.2\config\nbPython\debug\nbpythondebug\jpydaemon.py", line 1037, in dealWithCmd    exec(code) in myGlobals , myLocals
  File "<string>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list
>>>
Bei einer Ausführung über die Konsole erfolgt ein Abbruch.

Ich habe nun auch wieder den Aufrufpfad und die einzelnen Parameter in einem String zusammen gefasst. Es funktioniert aber auch in dieser Form mit der Liste:

Code: Alles auswählen

subprocess.Popen(['vlc', 'file:///D:\VLC\Videos\test.mp4', '--repeat'])
Eine Frage habe ich noch: Wenn ich den Aufruf über die IDE von NetBeans starte, dann erscheint das Konsolenfenster überhaupt nicht. Starte ich ihn durch einen Doppelklick auf die .py-Datei mit dem Aufrufcode, dann blitzt, wie bereits erwähnt, das Konsolenfenster kurz auf.

Gibt es eine Möglichkeit, das Konsolenfenster in jedem Fall zu unterdrücken?

MfG, kodela
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich verstehe nicht, wie du sagen kannst, dass du die `subprocess` Dokumentation gelesen hast und dann meinst, dein Aufruf haette funktionieren koennen:
https://docs.python.org/2/library/subprocess.html#frequently-used-arguments hat geschrieben:args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names). If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.
Eckige Klammern bedeuten immer dasselbe: Das ist ein Listenliteral (abgesehen von `__getitem__` Zugriffen auf Objekten). Eine Liste kann man nicht mit einem String konkatenieren, daher auch die Fehlermeldung.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@kodela: wenn da command steht, dann ist auch die Variable command gemeint, und wenn da args steht, dann ist da die Variable args gemeint, und keine Strings. Beide sind Argumente einer Funktion und das s bei args deutet an, dass es mehrere sind und mit wenig Phantasie kann man sich denken, dass es wohl eine Liste mit Argumenten sein soll. Dass man als erstes Argument von Popen auch einen String übergeben kann, ist nur dafür da, um in Foren Leute wie uns zur Verzweiflung zu treiben.

IDEs bringen oft ihre eigene Konsole mit. Eine .py-Datei mit Doppelklick zu starten ist falsche, da es sich um ein Konsolenprogramm handelt, und wie es der Name schon sagt, in einer Konsole gestartet werden sollte. Dateien mit der Endung .pyw sind mit einem Python ohne Konsole verknüpft, was aber bei der Fehlersuche nicht sehr hilfreich ist.
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

@cofi:
Ich habe nie behauptet, die Dokumentation zu den subprocess-Funktionen "gelesen" zu haben. Ich habe aber die Dokumentation durchgesehen und mir alles, was meiner Meinung nach relevant sein könnte, übersetzen lassen. Dabei fand ich nichts, was mir weiter geholfen hätte. Dass dafür meine fehlenden Englischkenntnisse ursächlich waren, darauf habe ich hingewiesen.

Dass Du in einem deutschsprachigen Forum nicht verstehst, wenn jemand hier Hilfe sucht, weil er einen komplexen englischen Text nicht rundum versteht, das verstehe nun ich nicht.

Deine Aussage, dass man eine Liste nicht mit einem String konkatenieren, also verketten kann, ist ohne Zweifel richtig, das verstehe ich sogar nach gut zwei Wochen, in denen ich mich nun mit Python beschäftige. Genau deswegen verstehen ich aber nicht, dass in dem von Dir verlinkten Beispiel diese Zeile

Code: Alles auswählen

return subprocess.Popen([command] + args, startupinfo=startupinfo).wait()
richtig sein soll, konkret das Argument "[command] + args". Müsste hier nicht "[command , args]" stehen?

Fasse das alles bitte nicht als "Gemotze" auf. Ich bin Dir für Deine Hilfe sehr dankbar.

@Sirius3:
Ja, das ist mir schon klar, dass für eine Variable grundsätzlich nicht einfach als Text verwendet werden kann. Da aber in diesem konkreten Fall die beiden Variablen command und args für Textstrings stehen müssen, habe ich es mir einfach gemacht und die Bezeichner als solche verwendet. Damit habe ich mir lediglich erspart, diese beiden Variablen vorher zu initialisieren. Ich hätte statt dessen auch einen Pfad für das aufzurufende Programm und ein beliebiges reales Argument eintragen können. Beide Eintragungen müssen in jedem Fall hier Textstrings sein.

Vielen Dank für Deinen Hinweis, dass Dateien mit der Endung .pyw mit einem Python-Aufruf ohne Konsole verknüpft sind. Das hat eigenartigerweise einmal auch so funktioniert. Mittlerweile blitzt aber auch mit der .pyw-Datei das Konsolenfenster auf. Ich weiß nicht, wie das zu verhindern ist.

MfG, kodela
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@kodela: was hilft es, wenn man ein Programm aufrufen will, irgendwelche unsinnigen Strings einzutragen??? Und nochmal args ist kein String, sondern eine Liste mit Strings. Um also cofis verlinktes Codebeispiel zu benutzen:

Code: Alles auswählen

launchWithoutConsole("vlc", ["file:///D:\VLC\Videos\test.mp4", "--repeat"])
Welche Datentypen verwendet werden sollen, kann man übrigens auch schon am Beispielaufruf sehen.
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

@Sirius3:
ich glaube, wir reden aneinander vorbei. Was Du schreibst, das ist absolut richtig und ich sehe das genau so. Ich wollte allerdings nie mit diesen unsinnigen Strings ein Programm aufrufen. Ich hatte lediglich Zweifel, ob ein Ausdruck "[command] + args" syntaktisch richtig sein kann und das habe ich mit unsinnigen Strings für sich alleine getestet.

Wie dieser Test es zeigt, ist der Ausdruck richtig, wenn, wie Du schreibst, args eine Liste ist :

Code: Alles auswählen

>>>cmd = "vlc"
>>>args = ['d:/pfad/datei.ext', '--parameter']
>>>x = [cmd] + args
>>>x
['vlc', 'd:/pfad/datei.ext', '--parameter']
Es ist doch aber verwirrend, wenn man wie hier im Beispiel cmd erst als String definiert, args als Liste und dann beide, indem man zuvor mit cmd eine Liste bildet, zu einer Liste verknüpft.

Man sollte in einem Forum wie diesem doch Verständnis dafür haben, dass jemand, der sich in eine Programmiersprache einarbeiten will, solche Konstruktionen suspekt vorkommen müssen. Noch dazu, wenn man in der Dokumentation zu subprocess.call() dieses Beispiel findet:

Code: Alles auswählen

subprocess.call("exit 1", shell=True)
Wo ist hier eine Liste?

Eine Frage noch: Was bedeutet das Argument mit dem Stern (*) in dieser Beschreibung von

Code: Alles auswählen

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
Ich finde dafür nirgend wo eine Erklärung. Auch vermisse ich eine Aussage darüber, welche der Argumente hier optional sind. Aus dem Beispiel kann ich lediglich schließen, dass bis auf das erste alle optional sind.

Für den Aufruf, ganz ohne Anzeige der Konsole habe ich noch keine Lösung gefunden. Verschiedentlich fand ich Hinweise auf eine Verlinkung mit Pythonw. Eine solche Datei (pythonw.exe) finde ich in meinem Installationsordner (Teil von OpenOffice 4) nicht.

MfG, kodela
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Welche Argumente optional sind und was der Stern bedeutet sind normale Python-Semantik: Alles was vorbelegt ist, ist optional und der Stern bedeutet beliebige Argumente. Aber das kann dir das Tutorial besser erklaeren: https://docs.python.org/2/tutorial/cont ... -functions

Was der Stern konkret bedeutet wird durch die Dokumentation leider nicht klar, aber das hier ist `subprocess.call`:

Code: Alles auswählen

def call(*popenargs, **kwargs):
    """Run command with arguments.  Wait for command to complete, then
    return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    return Popen(*popenargs, **kwargs).wait()
Und damit ist klar, dass es einfach nur seine Argumente an `subprocess.Popen` weitergibt.

Was `command` und `args` in dem verlinkten Code sein muessen wird doch durch das Beispiel deutlich. Warum diese Klimbzuege gemacht werden kann ich dir aber nicht sagen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@cofi, kodela: der Stern ist in Python 3 neu hinzugekommen und trennt Keyword-only-Argumente von normalen Argumenten.
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo cofi,

danke für die Aufklärung. Mit dem von Dir verlinktem Tutorial arbeite ich bereits, aber zugegebenermaßen nicht Schritt für Schritt, denn die Grundsätze des Programmierens sind mir bekannt. Also hangle ich mich so durch, suche nach Parallelen und Unterschieden zu C++ und Java und versuche mich an kleinen Beispielen, die für mich relevant sein könnten. Größere Objekte kommen sowieso nicht mehr in Frage, aber unter CALC von OpenOffice kann man doch einige Dinge mit Python zumindest eleganter lösen, als mit dem Basic von OpenOffice. Ja, und dabei stoße ich zum Teil auf Dinge, die mir spanisch vorkommen und stelle dann auch einmal dumme Fragen. Zuvor bemühe ich mich allerdings, wenn auch nicht immer erfolgreichen, selbst eine Antwort zu finden.

Nochmals Danke für die Hilfe, die mir in diesem Forum schon geleistet wurde.

MfG, kodela

PS: Eben sehe ich, dass Sirius zwischenzeitlich darauf aufmerksam gemacht hat, dass der Stern (*) erst mit der Version 3 eingeführt wurde. Danke
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Sirius3 hat geschrieben:@cofi, kodela: der Stern ist in Python 3 neu hinzugekommen und trennt Keyword-only-Argumente von normalen Argumenten.
Der ist auch praesent in der Python2 Dokumentation: https://docs.python.org/2/library/subpr ... ocess.call
Und tut ja auch das was ich sage ;) Aber danke, das wusste ich tatsaechlich noch nicht.

@kodela: Arbeite die ersten 9 Kapitel am besten am Stueck durch. Damit hast du dann sehr guten Ueberblick ueber alle Sprachkonstrukte und Vergleiche mit anderen Sprachen fallen einfacher. Uebrigens: Da du nur neu zu Python bist, faellst du genau in die Zielgruppe des Tutorials.
Antworten