Necesito bloquear un archivo para escribir en Python. Se accederá desde múltiples procesos de Python a la vez. He encontrado algunas soluciones en línea, pero la mayoría fallan para mis propósitos, ya que a menudo solo están basadas en Unix o Windows.
python
file-locking
Evan Fosmark
fuente
fuente
Aquí hay un módulo de bloqueo de archivos multiplataforma: Portalocker
Aunque, como dice Kevin, escribir en un archivo desde múltiples procesos a la vez es algo que desea evitar si es posible.
Si puede calzar su problema en una base de datos, puede usar SQLite. Admite acceso concurrente y maneja su propio bloqueo.
fuente
Las otras soluciones citan muchas bases de código externas. Si prefiere hacerlo usted mismo, aquí hay un código para una solución multiplataforma que utiliza las respectivas herramientas de bloqueo de archivos en sistemas Linux / DOS.
Ahora,
AtomicOpen
se puede usar en unwith
bloque donde normalmente se usaría unaopen
declaración.ADVERTENCIA: Si se ejecuta en Windows y Python se bloquea antes de que se llame a exit , no estoy seguro de cuál sería el comportamiento del bloqueo.
ADVERTENCIA: El bloqueo proporcionado aquí es informativo, no absoluto. Todos los procesos potencialmente competitivos deben usar la clase "AtomicOpen".
fuente
unlock_file
archivo en Linux no deberíafcntl
volver a llamar con laLOCK_UN
bandera?__exit__
ticlose
fuera de la cerradura despuésunlock_file
. Creo que el tiempo de ejecución podría vaciar (es decir, escribir) datos duranteclose
. Creo que uno debeflush
yfsync
debajo de la cerradura para asegurarse de que no se escriban datos adicionales fuera de la cerradura duranteclose
.flush
yfsync
. He agregado las dos líneas que sugirió antes de llamarunlock
. Volví a probar y la condición de carrera parece estar resuelta.Prefiero lockfile : bloqueo de archivos independiente de la plataforma
fuente
He estado buscando varias soluciones para hacer eso y mi elección ha sido oslo.concurrency
Es potente y relativamente bien documentado. Se basa en sujetadores.
Otras soluciones:
fuente
filelock
(Última publicación: 18 de mayo de 2019 en el momento del comentario)El bloqueo es específico de la plataforma y el dispositivo, pero en general, tiene algunas opciones:
Para todos estos métodos, deberá utilizar una técnica de bloqueo de giro (reintentar después de fallar) para adquirir y probar el bloqueo. Esto deja una pequeña ventana para la sincronización incorrecta, pero generalmente es lo suficientemente pequeña como para no ser un problema importante.
Si está buscando una solución que sea multiplataforma, es mejor que inicie sesión en otro sistema a través de algún otro mecanismo (la siguiente mejor opción es la técnica NFS anterior).
Tenga en cuenta que sqlite está sujeto a las mismas restricciones sobre NFS que los archivos normales, por lo que no puede escribir en una base de datos sqlite en un recurso compartido de red y obtener la sincronización de forma gratuita.
fuente
os.rename
ahora es atómica en Win32 desde Python 3.3: bugs.python.org/issue8828Coordinar el acceso a un solo archivo en el nivel del sistema operativo está lleno de todo tipo de problemas que probablemente no desee resolver.
Su mejor opción es tener un proceso separado que coordine el acceso de lectura / escritura a ese archivo.
fuente
flock
. Un enfoque de "rodar sus propios mutexes y un proceso de demonio para administrarlos" parece un enfoque bastante extremo y complicado de resolver ... un problema que no nos ha contado realmente, pero que apenas sugiere que existe.El bloqueo de un archivo suele ser una operación específica de la plataforma, por lo que es posible que deba permitir la posibilidad de ejecutarse en diferentes sistemas operativos. Por ejemplo:
fuente
He estado trabajando en una situación como esta donde ejecuto varias copias del mismo programa desde el mismo directorio / carpeta y errores de registro. Mi enfoque era escribir un "archivo de bloqueo" en el disco antes de abrir el archivo de registro. El programa comprueba la presencia del "archivo de bloqueo" antes de continuar y espera su turno si existe el "archivo de bloqueo".
Aquí está el código:
EDITAR --- Después de pensar en algunos de los comentarios sobre los bloqueos obsoletos anteriores, edité el código para agregar una verificación de la obsolescencia del "archivo de bloqueo". El tiempo de varios miles de iteraciones de esta función en mi sistema dio un promedio de 0.002066 ... segundos antes de:
justo después:
así que pensé que comenzaría con 5 veces esa cantidad para indicar la obsolescencia y monitorear la situación en busca de problemas.
Además, mientras trabajaba con el tiempo, me di cuenta de que tenía un código que no era realmente necesario:
que tenía inmediatamente después de la declaración abierta, por lo que la eliminé en esta edición.
fuente
Para agregar a la respuesta de Evan Fossmark , aquí hay un ejemplo de cómo usar filelock :
Cualquier código dentro del
with lock:
bloque es seguro para subprocesos, lo que significa que se terminará antes de que otro proceso tenga acceso al archivo.fuente
El escenario es así: el usuario solicita un archivo para hacer algo. Luego, si el usuario envía la misma solicitud nuevamente, informa al usuario que la segunda solicitud no se realiza hasta que finalice la primera solicitud. Por eso, uso el mecanismo de bloqueo para manejar este problema.
Aquí está mi código de trabajo:
fuente
Encontré una implementación simple y trabajada (!) De grizzled-python.
El uso simple os.open (..., O_EXCL) + os.close () no funcionó en Windows.
fuente
Puede encontrar pylocker muy útil. Se puede usar para bloquear un archivo o para bloquear mecanismos en general y se puede acceder desde múltiples procesos de Python a la vez.
Si simplemente desea bloquear un archivo, así es como funciona:
fuente