Tipos protegidos para acceso a ficheros

Chema Cortes py en ls-l.org
Mie Ago 17 19:18:34 CEST 2005


Javierin escribió:
> Los bloqueos que ofrecen los módulos posixfile y fcntl no son lo que
> busco o no sé usarlos...
> 
> Hay alguna forma de comprobar que un fichero esté abierto¿?

En estos temas dependes mucho de lo que te pueda ofrecer el sistema
operativo. Para la escritura en un fichero tienes por medio el buffer de
escritura del sistema operativo, y luego está el modo de sincronizar
clusters del sistema de ficheros. Querer fabricar un sistema de
semáforos para multiproceso a partir de ahí sólo puede llevarte a la
frustración.

En el caso que ponías en un mensaje anterior (el de portalocker) el
problema está con los buffers. Nada más hacer el write() debes aplicar
un flush() para descargar el buffer:


>>> f = open("/home/svenero/PFC/hecho/cookies/cookies.txt", 'r+')
>>> portalocker.lock(file, portalocker.LOCK_EX)
>>> f.write("Escrito con file. Antes de hacerlo con ola")
>>> f.flush()
>>> g = open("/home/svenero/PFC/hecho/cookies/cookies.txt", 'r+')
>>> g.write("Hecho con ola. A ver si sale")
>>> g.flush()
>>> f.close()
>>> g.close()


Obsevaciones:

 - con flush ya da igual si cierras antes uno u otro fichero
 - los bloqueos del sistema operativo son por procesos, por lo que aquí
   no tiene efecto el portalocker.
 - no emplees 'file' como nombre


A falta de algo mejor, te recomendaría una solución más "atómica" (nada
que ver con bombas :-):

  fname="/home/svenero/PFC/hecho/cookies/cookies.txt"
  file(fname, 'w+').write("Datos de la cookie")

Si es preciso, utiliza varios ficheros, pero que cada escritura se haga
en un sólo paso.


> Algo parecido a los tipos protegidos de Ada¿? Acceso restringido a una
> parte del código (donde tendría todas las funciones de acceso y
> modificación) para que no se pueda ejecutar hasta que no se termine de
> manejar el fichero¿?

Si buscas, puedes encontrar algunas demostraciones que usan
"decoradores" para implementar bloques de ejecución protegidos y métodos
sincronizados al estilo java:

  http://www.zefhemel.com/archives/2005/01/02/python-beauty


Para el python 2.5 está previsto que los generadores lleven iniciadores
y finalizadores, lo que se podrán crear mejores bloqueos y muchas otras
cosas.

Por ejemplo, bloquear un fichero para escritura será algo similar a ésto:

with opening("/mi/fichero.txt","w") as f:
  f.write(datos)



En cuanto a trabajar con multitarea, es algo más complicado para tratar
aquí. La idea es tener un "oyente" (listener) que siempre esté pendiente
de un puerto, que inicie la nueva conexión con el cliente y que la pase
un nuevo proceso. Para evitar problemas por denegación de servicio,
habría que implementar una cola de conexiones simultáneas, y muchas
otras cosas a tener en cuenta. Si te interesan estos temas, mírate cómo
lo hacen algunos de los frameworks WSGI como el cherrypy, pero para este
tipo de cosas resulta más conveniente delegar en apache.

WSGI
  http://www.python.org/peps/pep-0333.html

Cherrypy
  http://www.cherrypy.org

WSGI Explorations in Python
  http://linuxgazette.net/115/orr.html




Más información sobre la lista de distribución Python-es