180 votes

Verrouillage d'un fichier en Python

J'ai besoin de verrouiller un fichier pour l'écrire en Python. Il sera accessible à partir de plusieurs processus Python à la fois. J'ai trouvé quelques solutions en ligne, mais la plupart d'entre elles ne répondent pas à mes besoins car elles ne sont souvent basées que sur Unix ou Windows.

136voto

Evan Fosmark Points 17732

D'accord, donc j'ai fini par utiliser le code que j'ai écrit ici, sur mon site web le lien est mort, voir sur archive.org ( également disponible sur GitHub ). Je peux l'utiliser de la manière suivante :

from filelock import FileLock

with FileLock("myfile.txt.lock"):
    print("Lock acquired.")
    with open("myfile.txt"):
        # work with the file as it is now locked

1 votes

J'ai implémenté quelque chose de similaire, et j'ai juste découvert que ça cassait dans certaines configurations puisque NFSv2 ne supporte pas la création de fichiers exclusifs atomiques.

17 votes

Comme l'indique un commentaire sur l'article de blog, cette solution n'est pas "parfaite", car il est possible que le programme se termine de telle sorte que le verrou reste en place et que vous deviez supprimer manuellement le verrou avant que le fichier ne redevienne accessible. Cela mis à part, il s'agit d'une bonne solution.

0 votes

Est-ce la même chose que pythonhosted.org/lockfile/lockfile.html ? il semble être compatible, mais je ne suis pas sûr... Si c'est le même, le from filelock import FileLock ne fonctionne pas, utilisez from lockfile import FileLock au lieu de...

42voto

John Fouhy Points 14700

Il existe un module de verrouillage de fichiers multiplateforme ici : Portalocker

Bien que, comme le dit Kevin, écrire dans un fichier à partir de plusieurs processus à la fois est quelque chose que vous voulez éviter si possible.

Si vous pouvez transposer votre problème dans une base de données, vous pouvez utiliser SQLite. Il prend en charge les accès concurrents et gère son propre verrouillage.

25 votes

+1 -- SQLite est presque toujours la voie à suivre dans ce genre de situations.

2 votes

Portalocker nécessite Python Extensions for Windows, sur ce.

2 votes

@naxa il en existe une variante qui ne repose que sur msvcrt et ctypes, voir roundup.hg.sourceforge.net/hgweb/roundup/roundup/file/tip/

17voto

ferrdo Points 129

Je préfère fichier de verrouillage - Verrouillage des fichiers indépendant de la plate-forme

3 votes

Cette bibliothèque semble bien écrite, mais il n'y a pas de mécanisme pour détecter les fichiers de verrouillage périmés. Elle suit le PID qui a créé le verrou, il devrait donc être possible de savoir si ce processus est toujours en cours d'exécution.

1 votes

@sherbang : qu'en est-il supprimer_existant_pidfile ?

0 votes

@JanusTroelsen le module pidlockfile n'acquiert pas les verrous de manière atomique.

14voto

Richard Levasseur Points 5428

Le verrouillage est spécifique à la plate-forme et au dispositif, mais en général, vous avez quelques options :

  1. Utilisez flock(), ou un équivalent (si votre système d'exploitation le supporte). C'est un verrouillage consultatif, à moins que vous ne vérifiiez le verrouillage, il est ignoré.
  2. Utilisez une méthodologie de verrouillage-copie-déplacement-déverrouillage, où vous copiez le fichier, écrivez les nouvelles données, puis le déplacez (déplacer, pas copier - déplacer est une opération atomique sous Linux - vérifiez votre système d'exploitation), et vous vérifiez l'existence du fichier verrouillé.
  3. Utiliser un répertoire comme "verrou". Ceci est nécessaire si vous écrivez sur NFS, puisque NFS ne supporte pas flock().
  4. Il est également possible d'utiliser la mémoire partagée entre les processus, mais je n'ai jamais essayé ; c'est très spécifique au système d'exploitation.

Pour toutes ces méthodes, vous devrez utiliser une technique de verrouillage par rotation (réessayer après un échec) pour acquérir et tester le verrouillage. Cela laisse une petite fenêtre pour une mauvaise synchronisation, mais elle est généralement assez petite pour ne pas être un problème majeur.

Si vous recherchez une solution multiplateforme, il est préférable de vous connecter à un autre système via un autre mécanisme (la meilleure solution suivante est la technique NFS ci-dessus).

Notez que sqlite est soumis aux mêmes contraintes sur NFS que les fichiers normaux, donc vous ne pouvez pas écrire dans une base de données sqlite sur un partage réseau et obtenir la synchronisation gratuitement.

4 votes

Note : Déplacer/Renommer n'est pas atomique dans Win32. Référence : stackoverflow.com/questions/167414/

7 votes

Nouvelle note : os.rename est maintenant atomique dans Win32 depuis Python 3.3 : bugs.python.org/issue8828

9voto

Kevin Points 19613

La coordination de l'accès à un fichier unique au niveau du système d'exploitation pose toutes sortes de problèmes que vous ne souhaitez probablement pas résoudre.

Votre meilleure chance est d'avoir un processus séparé qui coordonne l'accès en lecture/écriture à ce fichier.

21 votes

"processus séparé qui coordonne l'accès en lecture/écriture à ce fichier" - en d'autres termes, mettez en place un serveur de base de données :-)

1 votes

C'est en fait la meilleure réponse. Dire simplement "utiliser un serveur de base de données" est trop simplifié, car une base de données n'est pas toujours le bon outil pour le travail. Et s'il s'agit d'un fichier texte brut ? Une bonne solution pourrait être de créer un processus enfant et d'y accéder via un tuyau nommé, un socket unix ou une mémoire partagée.

12 votes

-1 parce que c'est juste du FUD sans explication. Le verrouillage d'un fichier en écriture me semble être un concept assez simple que les systèmes d'exploitation proposent avec des fonctions telles que flock pour cela. Une approche consistant à "créer vos propres mutex et un processus démon pour les gérer" semble être une approche plutôt extrême et compliquée pour résoudre... un problème dont vous ne nous avez pas parlé, mais dont vous avez suggéré l'existence.

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