Externes Programm/ Bild öffnen und wieder beenden

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
VA84
User
Beiträge: 6
Registriert: Donnerstag 30. Juli 2015, 23:10

Hallo zusammen,

ich versuche momentan das letzte Bild in einem bestimmten Ordner mittels Python zu öffnen und es soll nach z.B. 5s wieder geschlossen werden. Leider komme ich mit dem Schließen des Bildes bzw. der Anwendung nicht weiter. Hoffe mir kann hier jemand weiterhelfen. Das ganze läuft unter Windows und Python 2.7.

Code: Alles auswählen

import subprocess
import os
import time

#Letztes Bild suchen
liste = [f for f in os.listdir('C:/Images') if f.endswith('.jpg')]
datei=("C:/Images/"+liste[len(liste)-1])

#Bild darstellen
proc = subprocess.Popen(datei, shell=True)
time.sleep(5)

print("ENDE")
Viele Grüße
VA
BlackJack

@VA84: `Popen`-Exemplare haben eine `terminate()`-Methode.

Du zeigst übrigens nicht das letzte Bild an, was immer das auch konkret bedeuten mag, sondern das Bild welches bei `os.listdir()` zufällig als letztes in der Ergebnisliste steht. Das mag zufällig immer das für Dich richtige sein, aber `os.listdir()` gibt keinerlei Garantien dafür in welcher Reihenfolge die Namen zurückgegeben werden.

Daten (und auch Code) sollte man nicht wiederholen, also das 'C:/Images' sollte nur einmal im Quelltext stehen.

Pfadteile setzt man mit `os.path.join()` zusammen, anstatt mit Zeichenkettenoperationen.

Ein Indexzugriff ``sequence[len(sequence) - 1]`` schreibt sich kürzer und einfacher als ``sequence[-1]``.

Die Klammern um den Ausdruck dessen Ergebnis `datei` zugewiesen wird, sind überflüssig.
VA84
User
Beiträge: 6
Registriert: Donnerstag 30. Juli 2015, 23:10

Hey BlackJack,

danke für die Tips. Ich werde es morgen ändern. Allerdings nach 5 Stunden suchen und probieren, habe ich etwas gefunden womit es funktioniert, aber ich glaube nicht das es der korrekte weg ist.

Code: Alles auswählen

import subprocess
import os
import time
import psutil
import signal

ls1 = set(psutil.pids())
#Letztes Bild suchen
liste = [f for f in os.listdir('C:/Images') if f.endswith('.jpg')]
datei=("C:/Images/"+liste[len(liste)-1])

#Bild darstellen
process = subprocess.Popen(datei, shell=True)


time.sleep(5)
ls2 = set(psutil.pids())
ls = ls2 - ls1
print(ls)
liste = list(ls)
pid = liste[0]
print (pid)
print(psutil.Process(pid))
os.kill(pid, signal.SIGTERM)
print("ENDE")

Was meinst du mit: @VA84: `Popen`-Exemplare haben eine `terminate()`-Methode.

Sorry, bin absoluter noob.

EDIT: Hab mal in der Docu etwas dazu gefunden. Mein Problem ist die Anwendung vom "subprocess.Popen.terminate()" auf meinen Code. Hättest du eventuell ein Beispiel für die Syntax?

Viele Grüße
VA84
Sirius3
User
Beiträge: 18266
Registriert: Sonntag 21. Oktober 2012, 17:20

@VA84: Du hättest an der richtigen Stelle suchen sollen. Nicht nur, dass die "Lösung" furchtbar umständlich ist, und 10 Zeilen Code durch die eine, die BlackJack erwähnt hat, ersetzbar wäre, Du beendest da im Zweifel ein beliebiges Programm, das halt zufällig an erster Stelle Deiner Liste steht.

Mit glob läßt sich wunderbar einfach Filtern:

Code: Alles auswählen

from glob import iglob
datei = max(iglob('C:/Images/*.jpg'))
BlackJack

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
from glob import iglob
from subprocess import Popen
from time import sleep


def main():
    process = Popen(max(iglob('C:/Images/*.jpg')), shell=True)
    sleep(5)
    process.terminate()
    process.wait()



if __name__ == '__main__':
    main()
Vorausgesetzt das ”letzte” Bild hat auch den lexicographisch gesehen ”grössten” Namen.
VA84
User
Beiträge: 6
Registriert: Donnerstag 30. Juli 2015, 23:10

Hallo zusammen,

vielen Dank für eure Antwort. Leider hat es mir gezeigt, dass ich noch viel zu lernen habe :wink:. Leider klappt das Schließen der Anwendung nicht. Ich habe in der Docu zu Popen.terminate() folgendes gefunden.
Popen.terminate()

Stop the child. On Posix OSs the method sends SIGTERM to the child. On Windows the Win32 API function TerminateProcess() is called to stop the child.

New in version 2.6.
Wenn ich "process.terminate()" durch "process.TerminateProcess()" ersetze, erhalte ich die Fehlermeldung, dass es den Befehl nicht in Popen existiert.
File "C:/Python27/Bild_anzeigen_forum.py", line 11, in main
process.TerminateProcess()
AttributeError: 'Popen' object has no attribute 'TerminateProcess'
Irgendwie komme ich mit der Docu nicht klar oder hab ich die Docu falsch interpretiert? Das ganze läuft unter Windows.

Viele Grüße
VA
BlackJack

@VA84: Wieso ersetzt Du denn die Methode `terminate()` durch etwas anderes? Die heisst halt `terminate()` und nicht anders. In der Beschreibung steht was *die* Methode dann macht.
VA84
User
Beiträge: 6
Registriert: Donnerstag 30. Juli 2015, 23:10

Hallo zusammen,

wenn es mit dem Befehl 'terminale()' nicht klappt, dann versuche ich etwas anderes. Das Programm läuft zwar mit deiner Idee ohne einen Fehler durch, aber wie schon erwähnt das geöffnete Bild wird nicht wieder geschlossen.

Viele Grüße
VA
BlackJack

@VA84: Wenn `terminate()` nicht funktioniert, dann ist es ziemlich wahrscheinlich das nicht der gestartete Prozess das Bild anzeigt sondern nur ein bereits laufendes Programm informiert das es ein (weiteres) Bild anzeigen soll und sich dann beendet. In dem Fall bekommst Du das Bild nicht mehr so einfach geschlossen weil Dein Programm keine Ahnung hat welcher Prozess das ist der das Bild anzeigt. Ob der von Dir gestartete Prozess nach den 5 Sekunden überhaupt noch läuft könntest Du mit der `poll()`-Methode feststellen. Wenn die nach der Wartezeit und ohne ein `terminate()` bereits einen Rückgabecode liefert, dann ist da nicht viel zu machen.
VA84
User
Beiträge: 6
Registriert: Donnerstag 30. Juli 2015, 23:10

Hallo zusammen,

der vollständigkeitshalber mein Code der unter Windows funktioniert.

Code: Alles auswählen

from __future__ import absolute_import, division, print_function
from glob import iglob
from subprocess import Popen
from time import sleep
import signal
from win32com.client import GetObject
import os

pfad = 'C:/Images/*.jpg'
prog = 'dllhost.exe'

def main():
    process = Popen(max(iglob(pfad)), shell=True)
    sleep(3)
    WMI = GetObject('winmgmts:')
    processes = WMI.InstancesOf('Win32_Process')
    for p in processes:
        if p.Properties_("Name").Value == prog:
            os.kill(p.Properties_("ProcessID").Value, signal.SIGTERM)

if __name__ == '__main__':
    main()
Vielen Dank für eure Unterstützung.

Viele Grüße
VA84
Sirius3
User
Beiträge: 18266
Registriert: Sonntag 21. Oktober 2012, 17:20

@VA84: Du weißt, was Du da tust? dllhost.exe wird für alles mögliche benutzt, wie der Name schon sagt ist es ein Host-Programm für DLLs. Unter anderem scheint es auch für die Darstellung von Bildern zuständig zu sein. Wenn Du nun alle dllhost.exe-Prozesse killst, ist es also durchaus möglich, dass da was beendet wird, was Du nicht beabsichtigt hast.
Antworten