Verhindern, dass eine Konsolenanwendung geschlossen wird, wenn sie nicht von einem vorhandenen Terminal aus aufgerufen wird?

8

Bei dieser Art von Frage gibt es viele Varianten. Allerdings möchte ich gerade verhindern, dass eine Konsolenanwendung in Python schließt, wenn sie nicht von einem Terminal (oder einer anderen Konsole, wie sie unter Windows genannt wird) aufgerufen wird. Ein Beispiel dafür ist das Doppelklicken auf eine .py -Datei aus dem Windows-Explorer.

Normalerweise verwende ich etwas wie das folgende Code-Snippet, aber es hat den unglücklichen Nebeneffekt des Betriebs, selbst wenn die Anwendung von einem vorhandenen Terminal aufgerufen wird:

%Vor%

Es wird auch angenommen, dass alle Windows-Benutzer die Anwendung über die Windows-Shell aufrufen und nur Windows-Benutzer das Programm von einem anderen Ort als einem vorhandenen Terminal ausführen können.

Gibt es einen (möglichst plattformübergreifenden) Weg, um zu erkennen, ob meine Anwendung von einem Terminal aufgerufen wurde und / oder ob es notwendig ist, eine "beliebige Taste drücken ..." -Funktionalität für die aktuell laufende Instanz bereitzustellen? Beachten Sie, dass die Umgehung von Batch-, Bash- oder anderen "Wrapper-Prozessen" sehr umständlich ist.

Update0

Alex Martelli Antwort unten, ich habe diese Funktion erstellt:

%Vor%

Wenn andere passende Antworten entstehen, werde ich mehr Code für andere Plattformen und Desktop-Umgebungen hinzufügen.

Update1

Im Sinne von pywin32 habe ich diese -Funktion erstellt, die sich verbessert das obige, mit der akzeptierten Antwort. Der auskommentierte Code ist eine alternative Implementierung, die von Update0 stammt. Wenn Sie pywin32 nicht verwenden möchten, folgen Sie dem Link im akzeptierte Antwort . Pausieren oder getch () probieren.

%Vor%     
Matt Joiner 13.02.2010, 19:43
quelle

2 Antworten

6

Zuerst ein Versuch, dich von cleveren Hacks zu befreien. Es ist vollkommen angemessen, eine separate Verknüpfung zu haben, die für die Ausführung vom Explorer aus ausgelegt ist, die etwas andere Dinge (wie das Offenhalten der Konsole) von dem Skript, das von der Befehlszeile verwendet werden soll, ausführt. Wie Alex bereits darauf hingewiesen hat, ist dies kein Problem bei Nix, und das Richtige ist, immer sauber zu beenden oder Ihre Benutzer werden sich beschweren.

Wenn Sie immer noch eine Problemumgehung wünschen, ist hier Code, um zu erkennen, wenn die Konsole Es muss verhindert werden, dass es schließt das ist einigermaßen sauber. Erfordert Windows 2000 oder höher, die Logik ist in dieser Funktion enthalten:

%Vor%

Grundsätzlich erhält es die PIDs des Prozesses, der die von Python verwendete Konsole besitzt, und unseres Prozesses. Wenn sie gleich sind, wird die Konsole beim Verlassen der Konsole verschwinden und muss offen gehalten werden. Wenn sie unterschiedlich sind oder wenn keine Konsole angeschlossen ist, sollte Python normal beendet werden.

    
gz. 14.02.2010, 13:38
quelle
3

Unter Unix sagt sys.stdin.isatty() zuverlässig, ob die Standardeingabe von einem terminalähnlichen Gerät kommt (oder auf andere Weise umgeleitet wird) und ähnlich für die gleiche Methode in sys.stdout und sys.stderr - also können Sie verwenden Diese Aufrufe bestimmen, ob die Anwendung interaktiv oder in einer nicht interaktiven Umgebung (z. B. einem Cron-Job) ausgeführt wird. Wie genau Sie diese verwenden möchten, hängt davon ab, was Sie tun möchten, wenn (zum Beispiel) Standardeingabe und -ausgabe zu einem Nicht-Terminal umgeleitet werden, aber Standardfehler ist zu einem Terminal geht - betrachten Sie jedes von den 8 Möglichkeiten, von allen von ihnen zu Nicht-Terminals zu keiner von ihnen umgeleitet, und entscheiden, was Sie in jedem Fall tun möchten.

Unter Windows ist die Situation anders, da das Ausführen einer .py -Datei (im Gegensatz zu einer .pyw -Datei) eine neue transiente Konsole erzeugt (es gibt unter Unix keine genau entsprechende Situation); Ich nehme an, das ist der Fall, mit dem Sie sich befassen wollen? (Oder geht es nur um die Umleitung von Standard-I / O-Streams zu Dateien, was in Windows etwa genauso wie in Unix möglich ist?). Ich denke, der beste Ansatz in Windows könnte darin bestehen, win32api.SetConsoleCtrlHandler zu verwenden, um einen Handler dafür zu setzen Ereignisse als CTRL_CLOSE_EVENT - Auf diese Weise sollte der Handler aufgerufen werden (in diesem Fall, wenn die Konsole geschlossen wird), wenn eine Konsole für den Prozess ist, aber ansonsten nicht. Oder wenn Sie nur darauf achten, ob eine Konsole überhaupt vorhanden ist oder nicht (und die Dinge lieber anders handhaben), versuchen Sie win32api.GetConsoleTitle im try -Bein einer try / except -Anweisung - es erzeugt eine Ausnahme (die Sie abfangen und darauf reagieren, indem Sie eine boolesche Variable von Ihnen setzen to False ) wenn es keine Konsole gibt und einfach funktioniert (in diesem Fall setzen Sie diese boolesche Variable auf True ), wenn eine Konsole ist.

    
Alex Martelli 13.02.2010 20:43
quelle