Stellen Sie sicher, dass nur eine Instanz des Programms ausgeführt wird
Gibt es eine Pythonic way", um nur eine Instanz eines Programms laufen?
Ist die einzige vernünftige Lösung, die ich mir ausgedacht habe versucht, führen Sie es als ein server auf irgendeinem port, dann zweite Programm beim binden an den gleichen port - Fehler. Aber es ist nicht wirklich eine gute Idee, vielleicht ist da etwas leichter als das?
(Unter Berücksichtigung, dass das Programm erwartet, dass manchmal scheitern, d.h. segfault - so Dinge wie "lock-Datei" wird nicht funktionieren)
- Vielleicht ist Ihr Leben wäre einfacher, wenn Sie aufgespürt und behoben, der segfault. Nicht, dass es eine einfache Sache zu tun.
- Es ist nicht in meiner Bibliothek, es ist in python libxml-Bindungen und extrem schüchtern - feuert nur einmal ein paar Tage.
- Python standard-Bibliothek unterstützt flock(), das ist das Richtige für Die moderne UNIX-Programme. Öffnen Sie einen port verwendet, einen Platz in einem viel eingeschränkter Namensraum, in der Erwägung, dass pidfiles werden mehr Komplex, wie Sie benötigen, um zu überprüfen, laufende Prozesse zu entkräften Ihnen sicher; Herde hat weder ein problem.
- s/UNIX/linux/ dort gehen Sie, FTFY.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der folgende code sollte den job tun, es ist cross-Plattform und läuft auf Python 2.4-3.2. Getestet habe ich es auf Windows, OS X und Linux.
Den neuesten code-version verfügbar ist singleton.py. Bitte Datei Fehler hier.
Installieren Sie neigen dazu, verwenden Sie eine der folgenden Methoden:
easy_install tendo
pip install tendo
Einfach,
cross-PlattformLösung, gefunden in eine andere Frage von zgoda:Viele wie S. Lott ' s Vorschlag, aber mit dem code.
fcntl
- Modul unter Windows (obwohl die Funktion könnte emuliert werden).Dieser code ist Linux-spezifisch. Es verwendet 'Abstrakt' UNIX-domain-sockets, aber es ist einfach und wird nicht verlassen, stale lock-Dateien um. Ich bevorzuge es, die Lösung da oben ist es nicht erforderlich, einen speziell reservierten TCP-port.
Die eindeutige Zeichenfolge
postconnect_gateway_notify_lock
können geändert werden, um zu ermöglichen, dass mehrere Programme, die eine einzelne Instanz durchgesetzt.Ich weiß nicht, ob es pythonic genug, aber in der Java-Welt hören auf einem definierten port ist eine ziemlich weit verbreitete Lösung, wie es funktioniert auf allen wichtigen Plattformen und hat keine Probleme mit abstürzenden Programmen.
Ein weiterer Vorteil des Zuhörens zu einem port ist, dass Sie könnten senden einen Befehl an die laufende Instanz. Zum Beispiel, wenn der Benutzer startet das Programm ein zweites mal, Sie könnten schicken Sie die ausgeführte Instanz einen Befehl zu sagen, es öffnet sich ein weiteres Fenster (das ist das, was Firefox macht, zum Beispiel. Ich weiß nicht, ob Sie die Verwendung von TCP-ports oder named pipes oder so etwas wie, dass, obwohl).
import socket; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.bind(('localhost', DEFINED_PORT))
. EinOSError
wird ausgelöst, wenn ein anderer Prozess ist gebunden an den gleichen port.Nie geschrieben python vor, aber das ist, was habe ich nur implementiert, in mycheckpoint, um zu verhindern, dass es gestartet wird, zweimal oder mehr, die von crond:
Gefunden Slava-N ' s Vorschlag, nachdem dieses posting in einem anderen Thema (http://stackoverflow.com/questions/2959474). Dieser ist als Funktion aufgerufen, sperrt die Ausführung von scripts-Datei (keine pid-Datei) und erhält die Sperre, bis das Skript beendet wird (normal oder Fehler).
Verwenden Sie eine pid-Datei. Sie haben einige bekannte Position, "/Pfad/zu/pidfile" und bei Start werden Sie etwas wie das hier tun (teilweise pseudocode, weil ich bin pre-Kaffee und nicht arbeiten wollen alle, dass die Festplatte):
So, in anderen Worten, Sie sind die überprüfung, ob eine PID-Datei vorhanden ist; falls nicht, schreiben Ihre pid-Datei. Wenn die PID-Datei existiert, dann überprüfen, um zu sehen, ob die pid ist die pid des Laufenden Prozesses; wenn dem so ist, dann hast du ein anderes live-Prozess läuft, also einfach abgeschaltet. Wenn nicht, dann wird der Vorherige Prozess abgestürzt ist, so melden Sie es, und schreiben Sie dann Ihre eigene pid aus der Datei in die Stelle der alten. Fahren Sie dann Fort.
Du bereits Antworten auf ähnliche Frage in einem anderen thread, also der Vollständigkeits halber sehen, wie das zu erreichen ist das gleiche auf Windows uning benannten mutex.
http://code.activestate.com/recipes/474070/
Diese arbeiten dürfen.
Versuchen, erstellen Sie eine PID-Datei an einem bekannten Speicherort. Wenn Sie es versäumen, jemand hat die Datei gesperrt haben, sind Sie fertig.
Wenn Sie fertig sind normalerweise, schließen und entfernen Sie die PID-Datei, so kann jemand anders überschreiben.
Können Sie wickeln Sie Ihr Programm in einem shell-Skript löscht die PID-Datei, selbst wenn Ihr Programm abstürzt.
Können Sie, auch, verwenden Sie die PID-Datei um das Programm zu töten, wenn es hängt.
Durch ein lock-Datei ist eine ganz Allgemeine Ansatz auf unix. Wenn es kracht, Sie haben zu bereinigen manuell. Sie konnte stor die PID in der Datei, und beim starten überprüfen, wenn ein Prozess mit dieser PID, das überschreiben der lock-Datei, wenn nicht. (Allerdings müssen Sie auch eine Sperre um das Lesen-Datei-check-pid-rewrite-Datei). Finden Sie, was benötigen Sie für das abrufen und prüfen pid in der os-Paket. Die gemeinsame Möglichkeit, zu überprüfen, wenn es einen Prozess mit einer bestimmten pid, ist es zu senden, eine nicht-tödliche signal.
Andere alternativen könnten in Kombination mit flock-oder posix-Semaphoren.
Öffnen einer Netzwerk-socket, als saua vorgeschlagen, wäre wahrscheinlich die einfachste und die meisten tragbaren.
Für jedermann mit wxPython für Ihre Anwendung, können Sie die Funktion
wx.SingleInstanceChecker
hier dokumentiert.Ich persönlich benutze eine Unterklasse von
wx.App
macht die Verwendung vonwx.SingleInstanceChecker
und zurückFalse
ausOnInit()
wenn es eine vorhandene Instanz von der app schon die Ausführung etwa so:Dies ist eine einfache drop-in-Ersatz für
wx.App
verbietet, dass mehrere Instanzen. Zu es verwenden, ersetzen Sie einfachwx.App
mitSingleApp
im code etwa so:Hier ist meine eventuelle Windows-only-Lösung. Fügen Sie den folgenden in ein Modul, vielleicht namens "onlyone.py' oder was auch immer. Unter anderem, dass Modul direkt in die __ main __ python-Skript-Datei.
Erklärung
Code versucht, erstellen Sie eine mutex mit dem Namen abgeleitet aus dem vollständigen Pfad zu dem Skript. Wir verwenden vorwärts-Schrägstriche, um möglichen Verwechslungen mit dem realen Dateisystem.
Vorteile
Ich bin dieses posting, als eine Antwort, denn ich bin ein neuer Benutzer und Stack Overflow nicht lassen Sie mich Stimmen noch.
Sorin Sbarnea ' s Lösung funktioniert bei mir unter OS X, Linux und Windows, und ich bin dankbar dafür.
Jedoch tempfile.gettempdir() verhält sich einen Weg unter OS X und Windows und die andere unter anderen einige/viele/alle(?) *Nixen (abgesehen von der Tatsache, dass OS X ist auch Unix!). Der Unterschied ist wichtig, diesen code.
OS X und Windows-Benutzer-spezifischen temp-Verzeichnisse, so dass ein tempfile erstellt von einem Benutzer nicht sichtbar für andere Benutzer. Durch den Gegensatz, unter vielen Versionen von *nix (getestet habe ich Ubuntu 9, RHEL 5, OpenSolaris 2008-und FreeBSD-8), das temp-dir ist /tmp für alle Benutzer.
Dass bedeutet, dass, wenn die Sperrdatei erstellt wird, die auf einem multi-user-Maschine, es ist in /tmp angelegt und nur die Benutzer, die erstellt die Sperrdatei der ersten Zeit wird in der Lage sein, um die Anwendung auszuführen.
Eine mögliche Lösung ist die Einbettung der aktuelle Benutzername im Namen der lock-Datei.
Es ist erwähnenswert, dass die OP ' s Lösung greifen ein port wird auch richtig in einer multi-user-Maschine.
Benutze ich
single_process
auf meinem gentoo;Beispiel:
finden: https://pypi.python.org/pypi/single_process/1.0
Die beste Lösung für dieses unter windows ist die Verwendung von Mutexe wie vorgeschlagen von @zgoda.
Einige Antworten verwenden
fctnl
(auch in @sorin tendo-Paket), die unter windows nicht verfügbar und sollten Sie versuchen, frieren Sie Ihre python-app mit einem Paket wiepyinstaller
die nicht statische Importe, wirft es einen Fehler.Auch über die lock-Datei-Methode erstellt ein
read-only
problem mit der Datenbank-Dateien( so erlebt mitsqlite3
).Halte ich besorge, es sollte eine gute POSIXy Lösung mit Prozess-Gruppen, die zimmerreserviereung, ohne das auf die Datei-system, aber ich kann mich nicht nail it down. So etwas wie:
Beim Start Ihres Prozesses sendet ein 'kill -0', um alle Prozesse in einer bestimmten Gruppe. Wenn solche Prozesse vorhanden ist, wird er beendet. Dann kommt in die Gruppe. Keine anderen Prozesse verwenden, die Gruppe.
Jedoch, dieser hat eine race-condition - mehrere Prozesse könnten alle tun dies, um genau die gleiche Zeit und am Ende schließt sich der Gruppe und gleichzeitig laufen. Durch die Zeit, die Sie Hinzugefügt haben, eine Art von mutex, um es wasserdicht ist, brauchen Sie nicht länger den Gruppen.
Dies könnte annehmbar sein, wenn der Prozess nur gestartet wird per cron einmal pro minute oder jede Stunde, aber es macht mich ein bisschen nervös, dass es schief gehen würde, genau auf den Tag, wenn Sie nicht wollen, es zu.
Ich denke, das ist nicht eine sehr gute Lösung sein, nachdem alle, es sei denn, jemand kann verbessern?
Lief ich in genau dieses problem Letzte Woche, und obwohl ich schon einige gute Lösungen, die ich beschlossen, eine sehr einfache und saubere python-Paket hochgeladen und es auf PyPI. Es unterscheidet sich von tendo, es kann sperren, string-name der Ressource. Sie könnten zwar sicherlich Sperre
__file__
erzielen den gleichen Effekt.Installieren mit:
pip install quicklock
Verwendung ist äußerst einfach:
Einen Blick: https://pypi.python.org/pypi/quicklock
linux-Beispiel
Diese Methode basiert auf der Erstellung einer temporären Datei automatisch gelöscht, nachdem Sie die Anwendung schließen.
das Programm starten, überprüfen wir die Existenz der Datei;
wenn die Datei vorhanden ist ( es gibt eine ausstehende Ausführung) , wird das Programm geschlossen ist, ansonsten erstellt er die Datei und setzt die Ausführung des Programms.
Auf einem Linux-system könnte man auch Fragen,
pgrep -a
für die Anzahl der Instanzen, die das Skriptgefunden in der Prozess-Liste (option-a zeigt die
vollständige Befehlszeilen-Zeichenfolge). E. g.
Entfernen
-u $UID
wenn die Beschränkung gelten soll alle Benutzer.Haftungsausschluss: a) es wird davon ausgegangen, dass das Skript (Basis)name eindeutig ist, b) es kann zu race conditions.