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é des solutions en ligne, mais la plupart échouent à mes fins car elles sont souvent uniquement basées sur Unix ou Windows.
python
file-locking
Evan Fosmark
la source
la source
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 dans la mesure du possible.
Si vous parvenez à intégrer votre problème dans une base de données, vous pouvez utiliser SQLite. Il prend en charge l'accès simultané et gère son propre verrouillage.
la source
Les autres solutions citent de nombreuses bases de code externes. Si vous préférez le faire vous-même, voici un code pour une solution multiplateforme qui utilise les outils de verrouillage de fichiers respectifs sur les systèmes Linux / DOS.
Maintenant,
AtomicOpen
peut être utilisé dans unwith
bloc où l'on utiliserait normalement uneopen
instruction.AVERTISSEMENT: si l'exécution sous Windows et Python se bloque avant l' appel de exit , je ne suis pas sûr du comportement de verrouillage.
AVERTISSEMENT: Le verrouillage fourni ici est indicatif et non absolu. Tous les processus potentiellement concurrents doivent utiliser la classe "AtomicOpen".
la source
unlock_file
fichier sur Linux ne devrait pas appeler àfcntl
nouveau avec leLOCK_UN
drapeau?__exit__
vous enclose
dehors de la serrure aprèsunlock_file
. Je crois que le runtime pourrait vider (c'est-à-dire écrire) des données pendantclose
. Je crois qu'il fautflush
etfsync
sous la serrure pour s'assurer qu'aucune donnée supplémentaire n'est écrite en dehors de la serrure pendantclose
.flush
etfsync
. J'ai ajouté les deux lignes que vous avez suggérées avant d'appelerunlock
. J'ai retesté et la condition de course semble être résolue.Je préfère lockfile - Verrouillage de fichiers indépendant de la plate-forme
la source
J'ai cherché plusieurs solutions pour ce faire et mon choix a été oslo.
C'est puissant et relativement bien documenté. Il est basé sur des attaches.
Autres solutions:
la source
filelock
(Dernière sortie: 18 mai 2019 au moment du commentaire)Le verrouillage est spécifique à la plate-forme et à l'appareil, mais en général, vous avez quelques options:
Pour toutes ces méthodes, vous devrez utiliser une technique de verrouillage rotatif (nouvelle tentative après échec) pour acquérir et tester le verrou. Cela laisse une petite fenêtre pour une mauvaise synchronisation, mais elle est généralement suffisamment petite pour ne pas être un problème majeur.
Si vous recherchez une solution multiplateforme, vous feriez mieux de vous connecter à un autre système via un autre mécanisme (la meilleure chose à faire est la technique NFS ci-dessus).
Notez que sqlite est soumis aux mêmes contraintes sur NFS que les fichiers normaux, vous ne pouvez donc pas écrire dans une base de données sqlite sur un partage réseau et obtenir une synchronisation gratuitement.
la source
os.rename
est désormais atomique dans Win32 depuis Python 3.3: bugs.python.org/issue8828La coordination de l'accès à un seul fichier au niveau du système d'exploitation comporte toutes sortes de problèmes que vous ne voulez probablement pas résoudre.
Votre meilleur pari est d'avoir un processus séparé qui coordonne l'accès en lecture / écriture à ce fichier.
la source
flock
. Une approche de "rouler vos propres mutex et un processus démon pour les gérer" semble être une approche plutôt extrême et compliquée à prendre pour résoudre ... un problème dont vous ne nous avez pas réellement parlé, mais que vous suggérez de façon effrayante existe.Le verrouillage d'un fichier est généralement une opération spécifique à la plate-forme, vous devrez peut-être prévoir la possibilité de s'exécuter sur différents systèmes d'exploitation. Par exemple:
la source
J'ai travaillé sur une situation comme celle-ci où j'exécute plusieurs copies du même programme à partir du même répertoire / dossier et des erreurs de journalisation. Mon approche était d'écrire un "fichier de verrouillage" sur le disque avant d'ouvrir le fichier journal. Le programme vérifie la présence du "fichier de verrouillage" avant de continuer, et attend son tour si le "fichier de verrouillage" existe.
Voici le code:
EDIT --- Après avoir réfléchi à certains des commentaires sur les verrous périmés ci-dessus, j'ai modifié le code pour ajouter une vérification de l'exactitude du "fichier de verrouillage". Le chronométrage de plusieurs milliers d'itérations de cette fonction sur mon système a donné une moyenne de 0,002066 ... secondes juste avant:
à juste après:
J'ai donc pensé que je commencerais avec 5 fois ce montant pour indiquer l'obsolescence et surveiller la situation pour les problèmes.
De plus, en travaillant avec le timing, j'ai réalisé que j'avais un peu de code qui n'était pas vraiment nécessaire:
que j'avais immédiatement après la déclaration ouverte, je l'ai donc supprimée dans cette modification.
la source
Pour ajouter à la réponse d'Evan Fossmark , voici un exemple d'utilisation de filelock :
Tout code dans le
with lock:
bloc est thread-safe, ce qui signifie qu'il sera terminé avant qu'un autre processus ait accès au fichier.la source
Le scénario est comme ça: l'utilisateur demande un fichier pour faire quelque chose. Ensuite, si l'utilisateur envoie à nouveau la même requête, il informe l'utilisateur que la seconde requête n'est pas effectuée tant que la première requête n'est pas terminée. C'est pourquoi, j'utilise un mécanisme de verrouillage pour gérer ce problème.
Voici mon code de travail:
la source
J'ai trouvé une implémentation simple et efficace (!) De grizzled-python.
L'utilisation simple os.open (..., O_EXCL) + os.close () ne fonctionnait pas sous Windows.
la source
Vous pouvez trouver pylocker très utile. Il peut être utilisé pour verrouiller un fichier ou pour verrouiller les mécanismes en général et est accessible à partir de plusieurs processus Python à la fois.
Si vous souhaitez simplement verrouiller un fichier, voici comment cela fonctionne:
la source