Una biblioteca Python simple y robusta para manejar bloqueos de archivo usando fcntl.flock, con soporte tanto para operaciones síncronas como asíncronas.
- Bloqueos síncronos: Clase
FileLockpara uso en código síncrono - Bloqueos asíncronos: Clase
AsyncFileLockpara uso conasyncio - Context managers: Uso seguro con
withyasync with - Timeouts configurables: Evita esperas indefinidas
- Debugging: Mensajes opcionales para debugging
- Thread-safe: Seguro para uso concurrente
- Tipado completo: Soporte completo de type hints para mejor IDE experience
- Sin dependencias: Solo usa la biblioteca estándar de Python
- Python 3.7+
- Sistema operativo Unix/Linux/macOS (requiere
fcntl) - No requiere dependencias externas
# Clonar el repositorio
git clone https://github.com/tu-usuario/filelock-sync-and-async.git
cd filelock-sync-and-async
# La biblioteca no requiere instalación adicional
# Solo asegúrate de tener Python 3.7+ instalado# Clonar el repositorio
git clone https://github.com/tu-usuario/filelock-sync-and-async.git
cd filelock-sync-and-async
# Crear entorno virtual con uv
uv venv
source .venv/bin/activate # Linux/macOS
# Instalar dependencias de desarrollo (opcional)
uv pip install -e ".[dev]"📋 Para instrucciones detalladas de uv, consulta UV_SETUP.md
filelock-sync-and-async/
├── src/ # Código fuente principal
│ ├── __init__.py # Módulo principal
│ ├── simple_filelock.py # Clase FileLock (síncrona)
│ └── simple_filelock_async.py # Clase AsyncFileLock (asíncrona)
├── examples/ # Ejemplos de uso
│ ├── sync/ # Ejemplos síncronos
│ │ ├── 01_basic_usage.py
│ │ ├── 02_timeout_example.py
│ │ └── 03_file_processing.py
│ ├── async/ # Ejemplos asíncronos
│ │ ├── 01_basic_async.py
│ │ ├── 02_concurrent_tasks.py
│ │ └── 03_web_scraping_simulation.py
│ ├── advanced/ # Casos de uso avanzados
│ │ ├── 01_mixed_sync_async.py
│ │ ├── 02_distributed_counter.py
│ │ └── 03_job_queue.py
│ ├── typing_example.py # Ejemplo de tipado y valores por defecto
│ └── run_all_examples.py # Script para ejecutar todos los ejemplos
├── tests/ # Tests (TODO)
├── pyproject.toml # Configuración del proyecto y dependencias
├── requirements-dev.txt # Dependencias de desarrollo
├── UV_SETUP.md # Guía detallada para usar con uv
├── CONTRIBUTING.md # Guía de contribución
└── README.md # Este archivo
from src.simple_filelock import FileLock
# Uso básico con context manager
with FileLock("/tmp/mi_app.lock"):
# Sección crítica - solo un proceso puede ejecutar esto a la vez
print("Ejecutando operación que requiere exclusividad...")
hacer_algo_importante()
# Uso con timeout
try:
with FileLock("/tmp/mi_app.lock", timeout=10, debug=True):
# Máximo 10 segundos esperando el lock
procesar_archivo_compartido()
except TimeoutError:
print("No se pudo obtener el lock en 10 segundos")import asyncio
from src.simple_filelock_async import AsyncFileLock
async def tarea_asincrona():
async with AsyncFileLock("/tmp/mi_app_async.lock", timeout=5):
# Sección crítica asíncrona
print("Ejecutando tarea asíncrona exclusiva...")
await procesar_datos_async()
# Ejecutar
asyncio.run(tarea_asincrona())- Uso Básico - Ejemplo más simple de uso
- Manejo de Timeouts - Múltiples procesos compitiendo por el mismo lock
- Procesamiento de Archivos - Caso práctico con archivo JSON compartido
- AsyncFileLock Básico - Introducción a bloqueos asíncronos
- Tareas Concurrentes - Múltiples workers asíncronos
- Simulación Web Scraping - Caso práctico con scrapers concurrentes
- Coordinación Mixta - Procesos síncronos y asíncronos coordinándose
- Contador Distribuido - Sistema de contador thread-safe
- Cola de Trabajos - Cola de trabajos distribuida completa
# Ejecutar el script que prueba todos los ejemplos
python examples/run_all_examples.py
# Con Makefile (si tienes uv instalado)
make examplesSi tienes uv instalado, puedes usar estos comandos para una experiencia más fluida:
# Configuración inicial completa
make setup && source .venv/bin/activate && make install-dev
# Ejecutar ejemplos
make examples
# Verificación completa antes de commit
make dev-check
# Formatear código
make format
# Ver todos los comandos disponibles
make helpclass FileLock:
def __init__(self, lockfile_path: str, timeout: Optional[float] = None, debug: bool = False) -> None:
"""
Crea una instancia de FileLock.
Args:
lockfile_path: Ruta del archivo de lock
timeout: Timeout en segundos. None = esperar indefinidamente
debug: Si True, imprime mensajes de debug
"""
def __enter__(self) -> 'FileLock':
"""Adquiere el lock (usado con 'with')"""
def __exit__(self, exc_type: Optional[type], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]) -> None:
"""Libera el lock automáticamente"""
def is_locked(self) -> bool:
"""Verifica si el archivo está bloqueado (solo para debugging)"""class AsyncFileLock:
def __init__(self, lockfile_path: str, timeout: Optional[float] = None, debug: bool = False) -> None:
"""
Crea una instancia de AsyncFileLock.
Args:
lockfile_path: Ruta del archivo de lock
timeout: Timeout en segundos. None = esperar indefinidamente
debug: Si True, imprime mensajes de debug
"""
async def __aenter__(self) -> 'AsyncFileLock':
"""Adquiere el lock de forma asíncrona (usado con 'async with')"""
async def __aexit__(self, exc_type: Optional[type], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]) -> None:
"""Libera el lock automáticamente"""
async def is_locked(self) -> bool:
"""Verifica si el archivo está bloqueado (solo para debugging)"""Las clases FileLock y AsyncFileLock incluyen tipado completo con type hints para una mejor experiencia de desarrollo:
from typing import Optional
from src.simple_filelock import FileLock
from src.simple_filelock_async import AsyncFileLock
# Tipado explícito para mejor autocompletado
lockfile_path: str = "/tmp/mi_app.lock"
timeout_segundos: Optional[float] = 5.0
debug_mode: bool = True
# El IDE puede inferir tipos automáticamente
with FileLock(lockfile_path, timeout=timeout_segundos, debug=debug_mode) as lock:
# lock es de tipo FileLock
is_locked: bool = lock.is_locked() # Retorna bool- 🎯 Autocompletado mejorado en IDEs como VS Code, PyCharm
- 🔍 Detección temprana de errores con herramientas como mypy
- 📝 Documentación automática de tipos esperados
- 🛡️ Mayor seguridad en refactoring y mantenimiento
# Instalar mypy para validación de tipos
pip install mypy
# Validar tipos en tu código
mypy mi_script.py# Evitar que múltiples instancias de un script se ejecuten simultáneamente
with FileLock("/tmp/mi_script.lock", timeout=0):
ejecutar_script_unico()# Múltiples procesos actualizando un archivo de configuración
with FileLock("/tmp/config.lock"):
config = cargar_configuracion()
config.update(nuevos_valores)
guardar_configuracion(config)# Múltiples scrapers guardando en el mismo archivo de resultados
async with AsyncFileLock("/tmp/resultados.lock"):
resultados = await cargar_resultados()
resultados.extend(nuevos_datos)
await guardar_resultados(resultados)# Sistema de cola distribuida
with FileLock("/tmp/jobs.lock"):
job = obtener_proximo_trabajo()
if job:
marcar_como_en_proceso(job)- Los bloqueos son por proceso, no por hilo
- Los archivos de lock se crean automáticamente si no existen
- Los directorios padre también se crean automáticamente
- Los bloqueos se liberan automáticamente cuando el proceso termina
- ✅ Linux: Completamente soportado
- ✅ macOS: Completamente soportado
- ✅ Unix: Completamente soportado
- ❌ Windows: No soportado (no tiene
fcntl)
- Los bloqueos son muy rápidos (microsegundos)
- No hay polling constante - usa bloqueos del sistema operativo
- Minimal overhead en aplicaciones high-performance
# Habilitar mensajes de debug
with FileLock("/tmp/test.lock", debug=True):
# Verás mensajes como:
# 🔒 Intentando adquirir lock en: /tmp/test.lock
# ✅ Lock adquirido.
# 🔓 Lock liberado.
pass- Fork el repositorio
- Crea una rama para tu feature (
git checkout -b feature/nueva-caracteristica) - Commit tus cambios (
git commit -am 'Agregar nueva característica') - Push a la rama (
git push origin feature/nueva-caracteristica) - Crea un Pull Request
Este proyecto está bajo la licencia MIT. Ver el archivo LICENSE para más detalles.
Si tienes preguntas o encuentras problemas:
- Revisa los ejemplos incluidos
- Verifica que estás en un sistema Unix/Linux/macOS
- Asegúrate de tener permisos de escritura en el directorio del lock
- Abre un issue en GitHub si necesitas ayuda adicional
- ✨ Nuevo: Tipado completo con type hints
- 🔧 Mejorado: Valores por defecto explícitos en constructores
- 📚 Nuevo: Ejemplo de tipado (
examples/typing_example.py) - 📖 Mejorado: Documentación de API con tipos
- 🎯 Mejorado: Soporte mejorado de IDEs
- 🚀 Nuevo: Soporte completo para
uvconpyproject.toml - 🛠️ Nuevo: Makefile con comandos automatizados
- 📋 Nuevo: Guía detallada UV_SETUP.md
- Implementación inicial de FileLock y AsyncFileLock
- Ejemplos completos de uso
- Documentación completa
- Soporte para timeouts y debugging