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

Plattformunabhängige GUIs mit wxWidgets.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Naja, der Code von Gerold ist zwar länger aber dafür halt flexibler. Er funktioniert mit Windows, Linux und sogar mit MacOS sollte es gehen. Bei dem Windows Teil hat er noch etliche Überprüfungen eingebaut, bei denen entschieden wird was für das PIDs holen genommen wird. Ein sehr gut durchdachte Sache.

Steckt übrigens seit heute bei mir im Library Verzeichnis und werde ich sicherlich für jedes Grafische Programm, das mit Lockfiles arbeite, verwenden 8)

lg
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Ich hab Gerolds Code sowohl unter Windows XP als auch unter Linux getestet... Zumindest dem ersten Antesten nach scheint das sehr sauber zu funktionieren, super!
Benutzeravatar
Blattlaus
User
Beiträge: 55
Registriert: Donnerstag 24. August 2006, 08:55

Unter Windows 2000 läuft er natürlich nicht. Genau so wenig unter NT und den älteren Sachen. Wobei da eigentlich nur 2000 relevant sein dürfte.
Ich weiß nicht, was ihr gegen die Methode mit dem Server habt, das läuft unter jedem Betriebssystem wo Python läuft.

/: Außerdem lese ich gerade, das tasklist.exe offenbar unter XP Home nicht dabei ist, wie es unter Vista aussieht, ist auch noch fraglich.
//: Ahja, unter Vista gibt es sie.
lunar

Blattlaus hat geschrieben:Unter Windows 2000 läuft er natürlich nicht. Genau so wenig unter NT und den älteren Sachen. Wobei da eigentlich nur 2000 relevant sein dürfte.
Das stimmt so nicht. Sie läuft nur dann nicht unter älteren System, wenn pywin32 oder ctypes nicht installiert sind. Eine dieser Bibliotheken als zusätzliche Abhängigkeit für Programme mitzuliefern, sollte doch - zumindest für normale Desktop-Anwendungen - kein Problem sein. Zumal ctypes doch bei Python 2.5 sowieso dabei ist...
Oder habe ich da den Code missverstanden?
Blattlaus hat geschrieben: Ich weiß nicht, was ihr gegen die Methode mit dem Server habt, das läuft unter jedem Betriebssystem wo Python läuft.
Sie ist halt - zumindest unter Linux - nur nicht wirklich Standard. Da sind Lockfiles mit pid die übliche Technik für sowas.
Außerdem vermeidet diese Technik, dass sämtliche Ports für localhost belegt sind, weil alle mögliche Programme ihre Server aufsetzen...

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

Blattlaus hat geschrieben:Ich weiß nicht, was ihr gegen die Methode mit dem Server habt, das läuft unter jedem Betriebssystem wo Python läuft.
Hi Blattlaus!

Ich habe mir deine Kritik zu herzen genommen und als Fallbacklösung noch den XMLRPC-Server mit eingebaut. :P

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

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Sie läuft nur dann nicht unter älteren System, wenn pywin32 oder ctypes nicht installiert sind.
In der Tat meckert py2exe, dass er diese Module nicht Einbinden konnte...
Da fehlt mir noch schlicht die Erfahrung, wie binde ich denn diese erfolgreich ein?
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

lunar hat geschrieben:[...]
Sie ist halt - zumindest unter Linux - nur nicht wirklich Standard. Da sind Lockfiles mit pid die übliche Technik für sowas.
Außerdem vermeidet diese Technik, dass sämtliche Ports für localhost belegt sind, weil alle mögliche Programme ihre Server aufsetzen...
[...]
Full ack!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

oliver1974 hat geschrieben:In der Tat meckert py2exe, dass er diese Module nicht Einbinden konnte... Da fehlt mir noch schlicht die Erfahrung, wie binde ich denn diese erfolgreich ein?
Hi oliver!

Bitte stelle diese Frage in einem neuen Thread. Oder vielleicht findest du hier in der Forensuche eine Antwort mit dem Stichwort ``py2exe``.

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:

...vielleicht hilft das: http://www.python-forum.de/post-46387.html#46387

Aber nur vielleicht -- ich persönlich verwende py2exe nicht und kann es deshalb nicht testen.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Danke soweit, ich werd das nochmal genau anschauen..

Dringend ist das nicht, für das Zielsystem (Windows XP) läuft trotz der Warnings alles bisher einwandfrei.
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Ich muss mal diesen alten Thread wieder nach vorne holen...

Mir ist da noch eine Sache aufgefallen, die unter Umständen für die Geschichte für Linux-Zielplattformen von Belang sein könnte... Das mit den Speichern der Sperrdatei in "/var/lock" könnte schiefgehen, da offensichtlich einige Distributionen eine etwas eigenwillige Interpretation der Rechte in diesem Verzeichnis haben... Wenn das Python-Skript mit "normalen" Benutzerrechten läuft, so hat es unter Umständen kein Schreibrecht auf "var/lock", je nachdem wie die Distri das so handhabt. Under Kubuntu (6.0.6 und 6.10) ist es kein Problem, da dort jeder schreiben darf, unter Mandriva (zumindest 2007.0, aber wenn ich einige alte LinuxUser-Artikel bezüglich anderer Applikationen mit ähnlichem Problemen richtig deute, auch schon ältere Versionen) aber zum Beispiel "von Haus aus" wieder nicht!

Entweder man passt nun die Rechte des Verzeichnisses an (kommt aber irgendwie schlecht rüber.. "ähh, für mein Programm müssten Sie mit Admin-Rechten erstmal etwas an den System-Verzeichnissen basteln) oder
man überlegt sich doch noch was anderes... Ich muss mir das mal ansehen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Davon ist in /var/lock schreiben nicht unbedingt schlau auf Multiuser-Systemen. Wenn ein User das Programm offen hat, kann ein anderer das nicht mehr. Viele Betriebssysteme ermöglichen es, mehrere User auch grafisch einzuloggen, daher kommt dieses Problem noch erschwerend hinzu.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Hmmm, berechtigter Einwand... Insofern müsste man sich den Code noch mal ganz neu ansehen....
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Leonidas hat geschrieben:Davon ist in /var/lock schreiben nicht unbedingt schlau auf Multiuser-Systemen. Wenn ein User das Programm offen hat, kann ein anderer das nicht mehr. Viele Betriebssysteme ermöglichen es, mehrere User auch grafisch einzuloggen, daher kommt dieses Problem noch erschwerend hinzu.
Hi!

Bei näherem Überlegen, scheint es sinnvoll, zu unterscheiden, ob ein Programm "global", also in der Betriebssystem-Instanz, oder "lokal", also nur für den Benutzer, nur einmal laufen darf.

Ein HTML-Server, der auf Port 80 horcht, sollte "global" nur einmal gestartet werden können.

Ein Programm mit GUI, das dem Benutzer ein paar Werte anzeigt, könnte auf einem System auch öfter ausgeführt werden, aber sollte (wenn gewünscht) nur einmal für den Benutzer ausgeführt werden.

Wie löst man diese Problematik? Beim Entwickeln des Programms könnte man einen Parameter setzen, der dieses Verhalten regelt.

Es ist kein Problem, eine Datei im Home-Ordner des Benutzers für solche Dinge heran zu ziehen. Die Schwierigkeit tritt auf, wenn ich ein Programm "global" sperren möchte. Wohin schreibe ich das Lockfile? Ein normaler Benutzer hat weder unter Windows noch unter Linux das Recht überall hin zu schreiben.

Gibt es einen Ort, an dem jeder Benutzer eines Systems eine Datei (exakt benannte) erstellen, bearbeiten und löschen darf?
Unter Linux könnte ich mir vorstellen, dass ``/tmp`` so ein Ort sein könnte. Aber unter Windows zeigt die Umgebungsvariable ``%TEMP%`` bei mir auf ``J:\DOKUME~1\Gerold\LOKALE~1\Temp``. Das ist garantiert kein Ordner, in den andere Benutzer schreiben dürfen.

Weiß jemand Rat? In welchen Ordnern darf jeder Benutzer schreiben und die Dateien anderer Benutzer verändern oder löschen?

Wenn wir diese Universalordner für Windows und Linux nicht finden, dann fällt mir nur XMLRPC ein. Dann müsste man beim Eruieren der Portnummer noch den Benutzernamen mit einbeziehen, um eine "lokale" Lösung zu erhalten.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Sollte ein Programm, dass global nur einmal gestartet werden darf nicht sowiso nur als root gestartet werden...

Und Port 80 darf ich bei mir sowiso nur als root verwenden...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gerold hat geschrieben:Ein HTML-Server, der auf Port 80 horcht, sollte "global" nur einmal gestartet werden können.
Dies ist sowieso sichergestellt, denn beim Versuch an einen Port zu horchen der von einem anderen Prozess schon benutzt wird, gibt es einen Fehler.
gerold hat geschrieben:Unter Linux könnte ich mir vorstellen, dass ``/tmp`` so ein Ort sein könnte. Aber unter Windows zeigt die Umgebungsvariable ``%TEMP%`` bei mir auf ``J:\DOKUME~1\Gerold\LOKALE~1\Temp``. Das ist garantiert kein Ordner, in den andere Benutzer schreiben dürfen.
Also im Explorer sehe ich einen Ordner Gemeinsame Dokumente unter XP, wenn man draufklickt kommt man in ``Dokumente und EInstellungen\All Users\Dokumente`` daher würde ich sagen, dass es möglcih wäre dass User in ``All Users`` schreiben könnten (ich denke dort ist auch ein Temp-Ordner). Allerdings finde ich es recht unlogisch, dass ``All Users`` schreibbar für nicht-Administratoren wäre.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Hallo,

Hmmm, bei mir ist zwar auch bei der Mandriva - Installation /tmp für alle schreibbar, aber keine Ahnung, ob das mal wieder bei einer anderen Distri abweicht.

Der Linux-Filesystem-Hierarchy-Standard schweigt sich zu den Zugriffsrechten zu /tmp aus, wenn ich das richtig interpretiere.

http://www.linux.com/guides/Linux-Files ... /tmp.shtml

Allerdings ist der Fall, dass ein Programm global läuft und dann auch nur einmal laufen darf, aber keine root-Rechte hat, in meinen Augen auch eher ungewöhnlich.. das sind in der Regel Dienste und die haben root-Rechte, da wäre die Lösung mit /var/lock dann wieder okay..

Zumindest aber sollten wir das Skript so abändern, dass bei "normalen" Anwendungen, die nur mit Userrechten laufen, der Lockfile im Home-Verzeichnis des Users sitzt. das wäre zumindest sinnvoll.

Ich meine mich auch erinnern zu können, dass die first_start.py Geschichte unter MacOSX nicht sauber lief.... habe ich aber nur mal aus dem Augenwinkel kurz gesehen, dazu müsste ich die Leute mit Zugriff auf MacOSX nochmal greifen und denen meine Skripte, die first_start.py benutzen, zukommen lassen.

Die Änderung mit dem Home-Directory wäre ja noch recht einfach
(Hier mal die Änderungen, wie ich sie habe.. ab Zeile 87 vom Original
her).

Code: Alles auswählen

        if appdatadir:
            lockdir = os.path.join(appdatadir, "Lockfiles")
        else:
            env_home = os.environ.get("HOME")
            appdir = os.path.join(env_home, appname)
            lockdir = os.path.join(appdir, "Lockfiles")
            
            if not (os.path.exists(lockdir) and os.path.isdir(lockdir)):
                os.makedirs(lockdir)
Man könnte sich jetzt überlegen, ob man nicht standardmäßig bei
"appname" noch den Punkt vorne hinzufügt, so hätte man dann gleich das
Verzeichnis bei den POSIX - Systemen versteckt... oder man
lässt es so und der Benutzer von first_start.py muss halt selbst
bei der Übergabe von appname daran denken...


EDIT:
-------

Ah, mist, sehe gerade, dass sich jetzt Windows und POSIX Systeme
bei meiner Variante unterschiedlich verhalten würden, natürlich
müssten dann die Windows-Systeme auch ihre Lockfiles erstmal
primär in das Home-Verzeichnis schieben... bis wir die Lösung
für unsere "Bei Bedarf sperre global" Problem haben.
Pass ich nochmal an.
Gibt es einen Ort, an dem jeder Benutzer eines Systems eine Datei (exakt benannte) erstellen, bearbeiten und löschen darf?
Unter Linux (oder umfassender, POSIX - Systemen) steht jetzt die Lösung noch aus... aber was spricht dagegen, unter Windows XP und Co.
%APPDATA% zu nehmen, also in der Regel
C:\Dokumente und Einstellungen\All Users\Anwendungsdaten
?

Wird doch eh schon in der bisherigen Version von first_start.py
verwendet... Das würde doch der Variante für das globale Sperren entsprechen? Was war daran falsch?
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Also vielleicht eher so:

EDIT: Funktioniert so natürlich noch nicht, da Windows keine
"HOME" Umgebungsvariable hat... Lade die benötigten Änderungen später
hoch.... Wenn ein befreundeter MacOSX-ler das auch mal bei sich getestet hat.)

Code: Alles auswählen

    def __init__(self, appname, global_lock = False):
        """
        Initialisiert die Klasse und legt den Lockfilenamen fest.
       
        :param appname: Eindeutiger Name der Anwendung. Anhand dieses
          Parameters wird der Name des Lockfiles oder der Serverport für den
          XMLRPC-Server generiert.
        :param global_lock: Wenn True, dann wird diese Anwendung systemweit
          nur einmal ausgeführt, auch bei Mehrbenutzer-Systemen.
        """
        self.appname = appname
        self.xmlrpcport = None
       
        # Lockfilename festlegen
        appdatadir = os.environ.get("APPDATA", None)
        # ACHTUNG: Entsprechendes Verzeichnis für 
        # POSIX - Systeme (Linux, BSD, MacOSX)
        # fehlt hier noch.
        
        if global_lock and appdatadir:
            lockdir = os.path.join(appdatadir, "Lockfiles")
        else:
            env_home = os.environ.get("HOME")
            appdir = os.path.join(env_home, appname)
            lockdir = os.path.join(appdir, "Lockfiles")
            
            if not (os.path.exists(lockdir) and os.path.isdir(lockdir)):
                os.makedirs(lockdir)

            (Hier der Rest....)

[/code]
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Hmm, unter MacOSX erweist es sich schwieriger als gedacht..

Grund: MacOSX hat KEIN /proc Verzeichnis... Auch bei FreeBSD
haben die das wohl geknickt, wenn es noch da ist, dann nur als Übergangslösung für Altanwendungen.....

Wie kommen wir denn jetzt an eine Liste mit den aktuellen PIDs?

EDIT: Mir fällt jetzt nur sowas ein wie "ps" als Befehl übergeben
und dann die Ausgabe parsen... Hmmm, funktioniert wenigstens weitgehend garantiert auf allen BSDs, und wenn man es ohne weitere Optionen startet sollte da auch kein Unterschied zwischen Linux/BSD/MacOSX zu erwarten sein, in der ersten Spalte steht immer die PID... Hmmm, sollte klappen.
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Okay, die neue Variante ist hier zu finden....
Antworten