Sicherstellen,dass eine wxPython-App nur 1x ausgeführt wird?

Plattformunabhängige GUIs mit wxWidgets.
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Sonntag 10. Dezember 2006, 00:19

Hallo nochmals,

Ist es irgendwie möglich, ohne den Umweg über ein Lock-File
oder dergleichen plattformübergreifend sicherzustellen, dass eine
wxPython - Applikation nur in einer Instanz ausgeführt wird?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sonntag 10. Dezember 2006, 14:32

Du kannst in deiner App einen XML-RPC oder sonstigen Server starten und beim start gucken ob man sich zu einem solchen Verbinden kann. Wenn ja: Programm läuft, also sofort beenden. Wenn nein, dann starten und Server laufen lassen.
Nein, elegant ist das nicht, aber effektiv. Und wenn dein Server nur auf local horcht, gibt das nichtmal ein Sicherheitsproblem.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Dienstag 12. Dezember 2006, 12:52

Hmm, ist natürlich ein Ansatz...

Nur was, wenn da zufälligerweise schon so ein Server läuft, es müsste ja dann schon was "einzigartiges" sein....
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 12. Dezember 2006, 13:59

oliver1974 hat geschrieben:Hmm, ist natürlich ein Ansatz...
Hi oliver!

...in etwa so:

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-

import wx
from thread import start_new_thread
from SimpleXMLRPCServer import SimpleXMLRPCServer
import xmlrpclib
import socket

PORT = 26214

wx.SetDefaultPyEncoding("iso-8859-1")


def is_first_client():
    """
    Gibt True zurück, wenn diese Anwendung nur einmal gestartet wurde
    """
    
    try:
        server = xmlrpclib.ServerProxy("http://localhost:" + str(PORT))
        return not bool(server.is_up())
    except socket.error:
        return True
    

def lock_app():
    """
    Startet einen XMLRPC-Server um die Anwendung für weitere Aufrufe zu sperren.
    """
    
    def is_up():
        return True
    
    server = SimpleXMLRPCServer(("localhost", PORT)) 
    server.register_function(is_up)
    server.serve_forever()


if __name__ == "__main__":
    
    app = wx.PySimpleApp()

    if is_first_client():
        # Anwendung sperren
        start_new_thread(lock_app, ())
        
        f = wx.Frame(None, -1, "Hallo")
        f.Center()
        f.Show()
        
        app.MainLoop()
    else:
        wx.MessageBox("Die Anwendung wurde bereits gestartet!")
Allerdings kann ich die Anwendung jetzt im Moment nicht unter Linux testen.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Dienstag 12. Dezember 2006, 16:07

Warum so kompliziert Leute? :D

Ne Datei im userspace/MyApp. Z.B.: Ne INI.

Wenn MyApp gestartet ist (Instanz 1), setzt es den wert auf True.

Code: Alles auswählen

isrun.ini
[status]
isrun = True
Wenn jetzt MyApp nochmal gestartet (Instanz 2) wird überprüft es erstmal ob "isrun" False ist. Wenn nicht da beendet sich MyApp.

Wenn Instanz 1 Beendet wird setzt es den Wert "isrun", kurz vorm ".destroy()"-Aufruf, auf Flase.

lg

EDIT: Die einfachste Lösung ohne irgendwelche Netzwerk geschichten ;)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 12. Dezember 2006, 16:24

XtraNine hat geschrieben:Warum so kompliziert Leute? :D
Hi XtraNine!

Weil nach einer Lösung ohne Lock-File gefragt wurde. Deine Lösung ist nichts anderes als ein komplizierteres Lockfile.

Plattformübergreifende Lockfile-Lösungen haben meist den Nachteil, dass diese nach einem Fehler im Programm den Start der Anwendung verhindern. Das kann man zwar umgehen, indem man ein paar Prüfungen einbaut. Z.B. ob das Lockfile älter als der Startzeitpunkt des Computers ist. Wenn ja, dann wird das Lockfile gelöscht und die Anwendung gestartet...

XMLRPC ist plattformunabhängig und wenn der Computer neu gestartet wurde, ist alles wieder im Originalzustand.

Wenn die Lockfile-Lösung durchdacht programmiert wurde, dann würde ich diese auf jeden Fall der XMLRPC-Lösung vorziehen. Aber wie ich schon schrieben -- es wurde nach einer Lösung ohne Lockfile gefragt. :wink:

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 12. Dezember 2006, 16:28

PS:

Das ideale Lockfile enthält die PID des gestarteten Programmes.

Wenn das Programm gestartet wird, wird zuerst geprüft ob es ein Lockfile gibt. Gibt es ein Lockfile, dann wird geprüft ob ein Programm mit der im Lockfile gespeicherten PID noch läuft. Wenn ja, dann wird das neu gestartete Programm beendet. Wenn nein, dann wird das alte Lockfile gelöscht und mit dem Start des neuen programms fortgesetzt.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 12. Dezember 2006, 16:36

...

Unter Windows und mit installiertem ``pywin32`` bekommt man die Liste der Prozesse so:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import os
import win32process

pid = os.getpid()
running_pids = win32process.EnumProcesses()

print "Eigener PID:", pid
print "Laufende Prozesse:", running_pids
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 12. Dezember 2006, 17:03

...

Unter Linux fällt mir nichts besseres ein, um die PIDs zu ermitteln:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import os

pid = os.getpid()

running_pids = []
for filename in os.listdir("/proc"):
    if os.path.isdir(os.path.join("/proc", filename)):
        try:
            running_pids.append(int(filename))
        except ValueError:
            pass

print "Eigene PID:", pid
print "Laufende Prozesse:", running_pids
lg
Gerold
:-)
Zuletzt geändert von gerold am Dienstag 12. Dezember 2006, 21:45, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
lunar

Dienstag 12. Dezember 2006, 17:42

Zum Überprüfen reicht unter Linux doch folgendes:

Code: Alles auswählen

# hier das lockfile mit pid auslesen
if pid in os.listdir('/proc'):
    sys.exit(0)
else:
    # Anwendung starten
Wozu also die komplette Prozessliste?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 12. Dezember 2006, 18:19

lunar hat geschrieben:Wozu also die komplette Prozessliste?
Hi lunar!

Gute Idee! 8)

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Dienstag 12. Dezember 2006, 19:54

gerold hat geschrieben:
XtraNine hat geschrieben:Warum so kompliziert Leute? :D
[...]
Weil nach einer Lösung ohne Lock-File gefragt wurde. Deine Lösung ist nichts anderes als ein komplizierteres Lockfile.
[...]
Oh, das hatte ich übersehen.
BTW: Deine Vorschläge für ein gutes Lock-File sind sehr gut 8) Werde ich mit übernehmen :)

P.S.: Leute das Forum ist erste Sahne!! 8)
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Mittwoch 13. Dezember 2006, 10:20

sape hat geschrieben: P.S.: Leute das Forum ist erste Sahne!! 8)
Dem ist eigentlich nix mehr hinzuzufügen!

Wegen dem Lock-File.. Ja, die Idee hatte ich natürlich auch schon,
nur ist es da eben das Problem (wie schon geschrieben) dass,
wenn die Anwendung sich nicht sauber beendet, der Lockfile
da stehen bleibt.. und schon ist das ganze nicht mehr so trivial.

Die Tipps gehören ja eigentlich ins Wiki, das Problem taucht ja
immer wieder mal auf..
lunar

Mittwoch 13. Dezember 2006, 10:35

oliver1974 hat geschrieben:Wegen dem Lock-File.. Ja, die Idee hatte ich natürlich auch schon,
nur ist es da eben das Problem (wie schon geschrieben) dass,
wenn die Anwendung sich nicht sauber beendet, der Lockfile
da stehen bleibt.. und schon ist das ganze nicht mehr so trivial.
Wieso?
Wenn du die PID im Lockfile speicherst, kannst du doch beim Starten der Anwendung die PID auslesen. Dann kannst du überprüfen, ob ein entsprechender Prozess läuft und ob er zu deiner ausführbaren Datei passt.

Was ist daran nicht trivial? Es ist auch nicht schwerer als einen Server zu starten, es ist nur ein bisschen mehr Code ;)

Gruß
lunar
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 13. Dezember 2006, 12:40

lunar hat geschrieben:...es ist nur ein bisschen mehr Code ;)
Hi lunar!

Das kann man laut sagen! :mrgreen:

http://www.python-forum.de/topic-8282.html

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten