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

Plattformunabhängige GUIs mit wxWidgets.
lunar

Well, das sieht aber aufwändig aus :shock:

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)
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
oliver1974
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...)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

oliver1974 hat geschrieben:Hmm, warum das
"sowieso nur unter linux",
os.getpid() geht doch laut Doku auch unter Windows, oder?
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:Legen wir noch mal eine Schippe drauf, wie siehts denn mit MacOSX
MacOSX ist auch nur ein Unix-Derivat.
Benutzeravatar
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.

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()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
lunar

gerold 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.
Ok, für Windows kann ich zu Hause - mangels Testsystem ;) - nichts entwickeln. Wenn man das Ganze wirklich platformunabhängig gestalten will, kommt man wohl um deine Lösung nicht herum.

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 ;)
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...
Antworten