159 votes

Python: un seul exemple de programme

Est-il un Pythonic moyen d'avoir une seule instance d'un programme en cours d'exécution?

La seule solution que j'ai trouvé est d'essayer de l'exécuter comme un serveur sur un port, puis la deuxième programme en essayant de se lier à même de port - échoue. Mais ce n'est pas vraiment une bonne idée, peut-être il ya quelque chose de plus léger que cela?

(Prendre en considération le fait que le programme devrait échouer parfois, c'est à dire erreur de segmentation - des choses comme "fichier de verrouillage" ne fonctionne pas)

Mise à jour: les solutions proposées sont beaucoup plus complexes et moins dépendante que d'avoir un port occupé avec un serveur qui n'existe pas, si je dois aller avec celui-là.

122voto

sorin Points 23747

Le code suivant devrait faire le travail, il est multi-plateforme et fonctionne sur Python 2.4-3.2. Je l'ai testé sur Windows, OS X et Linux.

from tendo import singleton
me = singleton.SingleInstance() # will sys.exit(-1) if other instance is running

La dernière version du code est disponible singleton.py. Veuillez soumettre des bogues ici.

Vous pouvez installer tendance à l'aide de l'une des méthodes suivantes:

57voto

Slava V Points 2259

Simple, croix-plate-forme de solution, trouvée dans une autre question par zgoda:

import fcntl, sys
pid_file = 'program.pid'
fp = open(pid_file, 'w')
try:
    fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    # another instance is running
    sys.exit(0)

Beaucoup comme S. Lott de la suggestion, mais avec le code.

42voto

Roberto Rosario Points 773

Ce code est spécifique à Linux ( il utilise le "résumé" des sockets de domaine UNIX ), mais il est simple et ne laissez pas obsolètes les fichiers de verrouillage de autour de. Je la préfère à la solution ci-dessus, car il ne nécessite pas une spécialement réservée port TCP.

try:
    import socket
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    ## Create an abstract socket, by prefixing it with null. 
    s.bind( '\0postconnect_gateway_notify_lock') 
except socket.error, e:
    error_code = e.args[0]
    error_string = e.args[1]
    print "Process already running (%d:%s ). Exiting" % ( error_code, error_string) 
    sys.exit (0) 

27voto

Joachim Sauer Points 133411

Je ne sais pas si c'est pythonic assez, mais dans le monde Java est en écoute sur un port défini, est assez largement utilisée de la solution, qu'il fonctionne sur toutes les grandes plates-formes et ne pas avoir de problèmes avec fracas des programmes.

Un autre avantage de l'écoute d'un port est que vous pouvez envoyer une commande à l'instance en cours d'exécution. Par exemple lorsque l'utilisateur démarre le programme une seconde fois, vous pouvez envoyer l'instance en cours d'exécution d'une commande pour demander l'ouverture d'une autre fenêtre (c'est ce que Firefox, par exemple. Je ne sais pas s'ils utilisent les ports TCP ou nommés ou quelque chose comme ça, " bien que).

11voto

Charlie Martin Points 62306

Utiliser un fichier pid. Vous avez des emplacement connu, "/chemin/vers/pidfile" et au démarrage, vous faites quelque chose comme cela (en partie, de pseudo parce que je suis pré-café et ne veulent pas travailler, tout ce dur):

import os, os.path
pidfilePath = """/path/to/pidfile"""
if os.path.exists(pidfilePath):
   pidfile = open(pidfilePath,"r")
   pidString = pidfile.read()
   if <pidString is equal to os.getpid()>:
      # something is real weird
      Sys.exit(BADCODE)
   else:
      <use ps or pidof to see if the process with pid pidString is still running>
      if  <process with pid == 'pidString' is still running>:
          Sys.exit(ALREADAYRUNNING)
      else:
          # the previous server must have crashed
          <log server had crashed>
          <reopen pidfilePath for writing>
          pidfile.write(os.getpid())
else:
    <open pidfilePath for writing>
    pidfile.write(os.getpid())

Donc, en d'autres termes, vous êtes en vérifiant si une pidfile existe; si non, écrivez votre pid pour ce fichier. Si le pidfile n'existe pas, vérifier pour voir si le pid est le pid d'un processus en cours d'exécution; si oui, alors vous avez un autre live processus en cours d'exécution, donc, vient de fermer. Si non, alors le processus précédent est écrasé, alors connectez-vous, puis d'écrire votre propre pid pour le fichier à la place de l'ancien. Puis continuer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X