Cómo prevenir una condición de carrera cuando múltiples procesos intentan escribir y luego leer de un archivo al mismo tiempo
Tengo el siguiente código (simplificado para mayor claridad):
import os
import errno
import imp
lib_dir = os.path.expanduser('~/.brian/cython_extensions')
module_name = '_cython_magic_5'
module_path = os.path.join(lib_dir, module_name + '.so')
code = 'some code'
have_module = os.path.isfile(module_path)
if not have_module:
pyx_file = os.path.join(lib_dir, module_name + '.pyx')
# THIS IS WHERE EACH PROCESS TRIES TO WRITE TO THE FILE. THE CODE HERE
# PREVENTS A RACE CONDITION.
try:
fd = os.open(pyx_file, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
except OSError as e:
if e.errno == errno.EEXIST:
pass
else:
raise
else:
os.fdopen(fd, 'w').write(code)
# THIS IS WHERE EACH PROCESS TRIES TO READ FROM THE FILE. CURRENTLY THERE IS A
# RACE CONDITION.
module = imp.load_dynamic(module_name, module_path)
(Parte del código anterior se toma prestado deesta respuesta.)
Cuando se ejecutan varios procesos a la vez, este código hace que solo uno se abra y escriba enpyx_file
(asumiendopyx_file
ya no existe) El problema es que a medida que este proceso está escribiendo apyx_file
, los otros procesos intentan cargarpyx_file
- los errores se generan en los últimos procesos, porque en el momento en que leenpyx_file
Está incompleto. (Específicamente,ImportError
s se generan porque los procesos intentan importar el contenido del archivo).
¿Cuál es la mejor manera de evitar estos errores? Una idea es que los procesos sigan intentando importarpyx_file
en un bucle while hasta que la importación se realice correctamente. (Esta solución parece subóptima).