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?
Sicherstellen,dass eine wxPython-App nur 1x ausgeführt wird?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
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.
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 (former) Modvoice
-
- User
- Beiträge: 97
- Registriert: Donnerstag 26. Oktober 2006, 15:01
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....
Nur was, wenn da zufälligerweise schon so ein Server läuft, es müsste ja dann schon was "einzigartiges" sein....
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi oliver!oliver1974 hat geschrieben:Hmm, ist natürlich ein Ansatz...
...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!")
mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Warum so kompliziert Leute? 
Ne Datei im userspace/MyApp. Z.B.: Ne INI.
Wenn MyApp gestartet ist (Instanz 1), setzt es den wert auf 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

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 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

- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi XtraNine!XtraNine hat geschrieben:Warum so kompliziert Leute?
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.

lg
Gerold

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

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.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
...
Unter Windows und mit installiertem ``pywin32`` bekommt man die Liste der Prozesse so:
mfg
Gerold

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
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
...
Unter Linux fällt mir nichts besseres ein, um die PIDs zu ermitteln:
lg
Gerold

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
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.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Zum Überprüfen reicht unter Linux doch folgendes:
Wozu also die komplette Prozessliste?
Code: Alles auswählen
# hier das lockfile mit pid auslesen
if pid in os.listdir('/proc'):
sys.exit(0)
else:
# Anwendung starten
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi lunar!lunar hat geschrieben:Wozu also die komplette Prozessliste?
Gute Idee!

mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Oh, das hatte ich übersehen.gerold hat geschrieben:[...]XtraNine hat geschrieben:Warum so kompliziert Leute?
Weil nach einer Lösung ohne Lock-File gefragt wurde. Deine Lösung ist nichts anderes als ein komplizierteres Lockfile.
[...]
BTW: Deine Vorschläge für ein gutes Lock-File sind sehr gut


P.S.: Leute das Forum ist erste Sahne!!

-
- User
- Beiträge: 97
- Registriert: Donnerstag 26. Oktober 2006, 15:01
Dem ist eigentlich nix mehr hinzuzufügen!sape hat geschrieben: P.S.: Leute das Forum ist erste Sahne!!
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..
Wieso?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.
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
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi lunar!lunar hat geschrieben:...es ist nur ein bisschen mehr Code
Das kann man laut sagen!

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.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Well, das sieht aber aufwändig aus
Also bei geht das irgendwie kürzer:
Der Code mag fehlerhaft sein, er entsprang meinem Gehirn gerade eben und ist nicht getestet
, aber so ähnlich könnte ein doch der Code für Lockfile aussehen, oder?
Aber da wir sowieso alle nach KLOC bezahlt werden...
Gruß
lunar

Also bei geht das irgendwie kürzer:
Code: Alles auswählen
import os
# sowieso nur unter linux, deswegen kein os.path.join
pid_file = os.path.expanduser('~'/'.foo'/'foo.pid')
# lesen
try:
f = open(pid_file)
try:
pid = f.read()
# überprüfen
if pid in os.listdir('/proc'):
# beenden
sys.exit()
finally:
# datei schließen
f.close()
except IOError:
# uups, nicht da => nix tun
pass
# starten
f = open(pid_file, 'w')
f.write(os.getpid())
f.close()
# beenden des programmes
os.remove(pid_file)

Aber da wir sowieso alle nach KLOC bezahlt werden...

Gruß
lunar
-
- User
- Beiträge: 97
- Registriert: Donnerstag 26. Oktober 2006, 15:01
Hmm, warum das
"sowieso nur unter linux",
os.getpid() geht doch laut Doku auch unter Windows, oder?
"Return the current process id. Availability: Unix, Windows. "
Legen wir noch mal eine Schippe drauf, wie siehts denn mit MacOSX
aus..
(Ich werde jetzt erstmal die Vorschläge bei mir integrieren und dann testen...)
"sowieso nur unter linux",
os.getpid() geht doch laut Doku auch unter Windows, oder?
"Return the current process id. Availability: Unix, Windows. "
Legen wir noch mal eine Schippe drauf, wie siehts denn mit MacOSX
aus..

(Ich werde jetzt erstmal die Vorschläge bei mir integrieren und dann testen...)
- Rebecca
- User
- Beiträge: 1662
- Registriert: Freitag 3. Februar 2006, 12:28
- Wohnort: DN, Heimat: HB
- Kontaktdaten:
Fuer Gerolds und lunars Methode benoetigt man aber nicht nur die PID des aktuellen Prozesses, sondern auch die PIDs aller laufender Prozesse. Und das geht halt mit Linux und Windows unterschiedlich.oliver1974 hat geschrieben:Hmm, warum das
"sowieso nur unter linux",
os.getpid() geht doch laut Doku auch unter Windows, oder?
MacOSX ist auch nur ein Unix-Derivat.oliver1974 hat geschrieben:Legen wir noch mal eine Schippe drauf, wie siehts denn mit MacOSX
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi lunar!
Einer der wichtigsten Gründe, warum ich mit Python entwickle --> Plattformunabhängigkeit.
Wir alle wissen, dass man meist weniger Code braucht, um nur für eine Plattform zu programmieren. Und *ja*, deine Lösung würde nach ein paar kleinen Änderungen unter Linux einwandfrei funktionieren.
``first_start.py`` ist so geschrieben, dass es als Erweiterungsmodul eingesetzt werden kann. So hat man wiederverwendbaren Code, der jetzt schon mindestens unter Linux, Cygwin und Windows läuft. Durch den Umweg über die gemeinsame Liste der PIDs ändert sich die Logik des Hauptprogrammes nicht -- auch wenn man es unter verschiedensten Betriebssystemen laufen lässt. Dem Hauptprogramm ist die Plattform komplett egal. Es ändert sich also nichts an dessen Programmlogik.
mfg
Gerold

Einer der wichtigsten Gründe, warum ich mit Python entwickle --> Plattformunabhängigkeit.
Wir alle wissen, dass man meist weniger Code braucht, um nur für eine Plattform zu programmieren. Und *ja*, deine Lösung würde nach ein paar kleinen Änderungen unter Linux einwandfrei funktionieren.
``first_start.py`` ist so geschrieben, dass es als Erweiterungsmodul eingesetzt werden kann. So hat man wiederverwendbaren Code, der jetzt schon mindestens unter Linux, Cygwin und Windows läuft. Durch den Umweg über die gemeinsame Liste der PIDs ändert sich die Logik des Hauptprogrammes nicht -- auch wenn man es unter verschiedensten Betriebssystemen laufen lässt. Dem Hauptprogramm ist die Plattform komplett egal. Es ändert sich also nichts an dessen Programmlogik.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
from first_start import FirstStart
def main():
fs = FirstStart("testapplikation")
if fs.is_first_start():
fs.create_lockfile()
###################################################
### Hier wird gearbeitet. ###
### ###
### Es ist auch egal, ob das Programm unter ###
### Linux oder Windows läuft. ###
### Man sollte ab und zu darauf achten, ###
### Code zu schreiben, den man wiederverwenden ###
### kann. ###
### ###
### http://www.python-forum.de/topic-8282.html ###
### ###
###################################################
fs.delete_lockfile()
else:
print "Das Programm wurde bereits gestartet."
if __name__ == "__main__":
main()
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Ok, für Windows kann ich zu Hause - mangels Testsystemgerold hat geschrieben:``first_start.py`` ist so geschrieben, dass es als Erweiterungsmodul eingesetzt werden kann. So hat man wiederverwendbaren Code, der jetzt schon mindestens unter Linux, Cygwin und Windows läuft.

Was aber wiederrum die LOC für oliver1974 sehr reduziert: Für die Lockfile-Lösung kann er ja einfach auf dein Modul zurückgreifen
