Outils pour utilisateurs

Outils du site


empecher_double_exec

Empêcher qu'un programme ne soit lancé 2 fois

Problématique

Il existe des cas où il faut empêcher un programme d'être lancé 2 fois. Par exemple parce que le programme mobilise du hardware. Ou parce que le programme doit agir de façon unique sur des données. Etc…

Mais comment faire? La solution trouvée doit répondre à 2 conditions:

1- le programme doit “s'apercevoir” qu'une instance précédente est encore active.

2- en cas d'arrêt anormal (plantage), il doit être possible de relancer le programme

La solution proposée ici repose sur le verrouillage d'un fichier. Elle est multiplateforme, mais les instructions ne sont pas identiques pour les différents OS.

Codage proposé

Les fonctions de verrouillage se trouvent dans un module appelé, par exemple “verroufichier.py”, et codé comme suit:

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Python v2.7
 
import sys
 
#############################################################################
def lockfile_unix(f):
    """Unix: verrouille le fichier dont le descripteur est f """
    lockf(f.fileno(),  LOCK_EX | LOCK_NB)
 
#############################################################################
def lockfile_win(f):
    """Windows: verrouille le fichier dont le descripteur est f """
    locking(f.fileno(), LK_NBLCK, 1)
 
#############################################################################
def lockfile_rien(f):
    """Ni Windows ni Unix: cette fonction ne fait rien """
    pass
 
#############################################################################
lockfile = None
 
# si Unix
try:
    from fcntl import lockf, LOCK_NB, LOCK_EX
    lockfile = lockfile_unix
except:
    pass
 
# si Windows:
if lockfile == None:
    try:
        from msvcrt import locking, LK_NBLCK, LK_UNLCK
        lockfile = lockfile_win
    except:
        pass
 
# si aucune des 2 importations ne marche:
if lockfile == None:
    lockfile = lockfile_rien


Et voilà un exemple d'utilisation:

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import os, sys
import time
from verroufichier import lockfile
 
#############################################################################
def bidon():
    """programme qui ne fait rien d'autre que d'attendre 15 secondes de CPU"""
    t0 = time.clock()
    while True:
        if time.clock()-t0 > 15:
            break
 
#############################################################################
if __name__ == '__main__':
 
    # tentative de verrou sur le fichier témoin (mettre le bon chemin)
    nfc = "fichierverrou.txt"
    f = None
    try:
        f = open(nfc, 'w')
        lockfile(f)
    except:
        if f != None:
            f.close()
        print u"Echec: il y a déjà une 1ère instance en cours!"
        sys.exit()
 
    bidon()
 
    f.close() # le fichier témoin doit rester ouvert jusqu'à la fin du programme   

On peut vérifier que le verrou, une fois mis sur le fichier, disparait bien avec l'arrêt du programme, même un arrêt anormal.

Le fichier témoin peut être placé selon le problème à résoudre. Par exemple:

  • empêcher la double exécution sur un même PC pour tous les utilisateurs: fichier témoin dans un répertoire commun.
  • empêcher la double exécution pour un même utilisateur: fichier témoin dans le répertoire utilisateur.
  • empêcher la double exécution pour un répertoire de données: fichier dans ce répertoire.


Amusez-vous bien!

empecher_double_exec.txt · Dernière modification: 2011/02/17 21:47 de tyrtamos

Outils de la page