2010-09-22 15 views
25

Tengo que abrir un objeto similar a un archivo en python (es una conexión en serie a través de/dev /) y luego lo cierro. Esto se hace varias veces en varios métodos de mi clase. Lo que estaba haciendo era abrir el archivo en el constructor y luego cerrarlo en el destructor. Aunque estoy obteniendo errores extraños y creo que tiene que ver con el recolector de basura y tal, todavía no estoy acostumbrado a no saber exactamente cuándo se están eliminando mis objetos = \Implementación del uso de 'with object() como f' en clase personalizada en python

La razón por la que estaba haciendo esto es porque tengo que usar tcsetattr con un montón de parámetros cada vez que lo abro y se pone molesto haciendo todo eso por todos lados. Así que quiero para implementar una clase interna para manejar todo eso para que pueda usarlo haciendo
with Meter('/dev/ttyS2') as m:

que estaba buscando en línea y no pude encontrar una buena respuesta sobre cómo se implementa la sintaxis with. Vi que usa los métodos __enter__(self) y __exit(self)__. Pero, ¿es todo lo que tengo que hacer para implementar esos métodos y puedo usar la sintaxis? ¿O hay más?

¿Hay algún ejemplo sobre cómo hacer esto o alguna documentación sobre cómo se implementa en objetos de archivos que ya puedo ver?

Respuesta

36

Aquellos los métodos son prácticamente todo lo que necesita para que el objeto funcione con la instrucción with.

En __enter__ tiene que devolver el objeto de archivo después de abrirlo y configurarlo.

En __exit__, tiene que cerrar el objeto de archivo. El código para escribir estará en el cuerpo de la declaración with.

class Meter(): 
    def __init__(self, dev): 
     self.dev = dev 
    def __enter__(self): 
     #ttysetattr etc goes here before opening and returning the file object 
     self.fd = open(self.dev, MODE) 
     return self.fd 
    def __exit__(self, type, value, traceback): 
     #Exception handling here 
     close(self.fd) 

meter = Meter('dev/tty0') 
with meter as m: 
    #here you work with the file object. 
    m.read() 
+1

'def __enter __ (self): return self' si quiere una referencia a' Meter' en el bloque with. – Morgoth

3

El primer Google golpe (para mí) lo explica bastante simplemente:

http://effbot.org/zone/python-with-statement.htm

y el PEP lo explica con mayor precisión (pero también más extensamente del):

http://www.python.org/dev/peps/pep-0343/

+1

De hecho los vi y pensé que ninguno de ellos era muy claro. El primero dice "Hay métodos llamados \ __ enter__ y \ __ exit__" y explica poco o nada acerca de ellos. Y el PEP prácticamente solo habla de la necesidad de la nueva sintaxis – Falmarri

+0

No, es sencillo con ejemplos y explicaciones. Necesitas leerlo de nuevo; esta no es una característica compleja. –

11

más fácil puede ser el uso de módulo estándar Python biblioteca contextlib:

import contextlib 

@contextlib.contextmanager 
def themeter(name): 
    theobj = Meter(name) 
    yield theobj 
    theobj.close() # or whatever you need to do at exit 

Esto no hace Meter sí mismo un gestor de contexto (y por lo tanto no es invasivo a esa clase), sino más bien " decora "it (no en el sentido de la sintaxis del decorador de Python), sino casi, pero no del todo, en el sentido del patrón de diseño del decorador ;-) con una función de fábrica themeter que es un administrador de contexto (que el contextlib.contextmanager decorador crea desde t La función del generador "solo-yield" que escriba) - esto hace que así que sea mucho más fácil separar la condición de entrada y salida, evite la anidación, & c.

Cuestiones relacionadas