2011-03-17 4 views
8

Python tiene el maravilloso módulo collections que tiene herramientas que le permiten implementar un completo dict (por ejemplo) a partir de un conjunto mínimo de métodos. ¿Hay algo similar para la interfaz file en Python? Si no es así, ¿qué recomendaría como un conjunto mínimo de métodos para implementar para un objeto similar a file para fines de tipado de pato?¿Cuál es el subconjunto mínimo de métodos de archivos que necesito implementar para obtener la interfaz completa de archivos de Python?

¿Y cómo maneja cosas que le gustaría utilizar su archivo como objeto en una declaración with, como puede hacerlo con un archivo normal o que quiera iterar sobre él (como puede hacerlo con un archivo normal) o ¿Quién quiere poder llamar al readline o al readlines y hacer algo inteligente y útil (como se puede hacer con un archivo normal)? ¿Tienes que implementarlos todos tú mismo? ¿O hay mejores opciones?

Sé que puedo implementar todos y cada uno de estos, a mano. Pero la interfaz collections me permite implementar un dict implementando solo __len__, __iter__, __setitem__ y __getitem__. Consigo pop, popitem, clear, update, setdefault, __contains__, keys, items, values, get, __eq__ y __ne__ todo gratis. Hay una interfaz mínima para __dict__ definida, y si la implemento, obtengo la interfaz completa dict, implementando todos los métodos adicionales en términos de la interfaz mínima.

Del mismo modo, me gustaría saber cuál es la interfaz mínima para el archivo que tengo que implementar para obtener la interfaz completa. ¿Hay una manera de conseguir __enter__, __exit__, readline, readlines, __iter__ y next si acabo de implementar read, write y close, o tengo que poner en práctica todo lo que a mí mismo con la mano cada vez que quiero la interfaz completa file?

Respuesta

3

El con declaración requiere un gestor de contexto:

http://docs.python.org/library/stdtypes.html#typecontextmanager

El tipo de archivo está completamente definido:

http://docs.python.org/library/stdtypes.html#file-objects

Parece bastante simple.

La documentación enumera los métodos y atributos de un archivo y un administrador de contexto. Implementa esos.

¿Qué más información necesita?

http://docs.python.org/library/contextlib.html?highlight=context%20manager

si desea que todos los métodos de trabajo, usted tiene que poner en práctica todos los métodos. A diferencia de las colecciones, no hay una clase base abstracta para los archivos.

+0

Quiero saber, ¿hay alguna manera de evitar tener que implementar todo eso yo mismo? Ya hay un administrador de contexto para los objetos similares a archivos, ya hay un buffer de línea para objetos similares a archivos, ya hay un iterador para objetos similares a archivos. ¿Hay alguna forma de que pueda usarlos en lugar de tener que implementarlos yo mismo? Me gustaría poder hacerlo solo con la implementación de un método de "lectura" y "escritura". – Omnifarious

+1

@Omnifarious. Usted solo implementa lo que su aplicación realmente necesita. Si su aplicación solo necesita leer y escribir, eso es todo lo que implementa. Un "buffer de línea" no tiene sentido. Un iterador es trivial (es una función con 'yield'.) El gestor de contexto, de manera similar, se puede utilizar desde el paquete' contextlib'. Puede que no sea mucho código. Dado que su pregunta es vaga, la respuesta debe ser necesariamente vaga. Si proporcionó algunos ejemplos de cómo desea utilizar su nuevo objeto similar a un archivo, podríamos proporcionarle consejos más concretos. –

+0

@Omnifarious. Si desea que todos los métodos funcionen, debe implementar todos los métodos. A diferencia de las colecciones, no hay una clase base abstracta para los archivos. –

2

Me gustaría ver io.IOBase [1] y io.RawIOBase para> 2.6 compatibilidad. Esto lo mantendrá avanzando con 3.x (io implementa la interfaz de archivos 3.x).

[1] http://docs.python.org/library/io.html#i-o-base-classes

+0

Estos parecen un comienzo en lo que busco, pero la documentación para ellos es un poco confusa. De todos modos, gracias por señalarme a ellos. – Omnifarious

+0

de nada, después de leer su otro comentario TextIO podría ser lo que realmente desea. –

+0

En lo que no estoy seguro, ¿puede darle TextIO algo que implemente RawIOBase y obtener una interfaz TextIO para él? – Omnifarious

2

De alguna manera respondidas por sí mismo. Si bien no hay un conjunto de métodos "especiales" que necesita para implementar la interfaz de archivos, puede hacerlo simplemente proporcionando un par de métodos normalmente asociados con los archivos. Duck typing se ocupa del resto.

Solo necesita realmente un read y/o un método write (dependiendo de si desea que sea legible y/o escribible) que se comportan igual que un objeto de archivo normal. Puede echar un vistazo a la referencia Python file object para ver todos los métodos de un objeto de archivo. Básicamente, cuanto más implemente, más situaciones su clase funcionará en lugar de un archivo. (Por ejemplo, si implementa seek, funcionará en cualquier función que realice búsquedas en un archivo). Tenga en cuenta que aquí hay un continuo, no hay absoluto "admite el protocolo de archivo o no". De hecho, no hay forma de trabajar al 100% en todos los lugares compatibles con objetos similares a archivos, ya que algunos códigos accederán a detalles de bajo nivel del tipo real file, y el suyo no funcionará allí.

En resumen, cualquier clase que implemente read y write funcionará en la mayoría de las situaciones que requieren un "objeto similar a un archivo".

(Tenga en cuenta que los nombres especiales como método para __getitem__ predice realmente no son especiales, excepto que se utilizan por la sintaxis especial como [key] -. Es por eso que dict tiene los nombres de métodos especiales y archivo no)

+2

Entiendo sobre 'leer' y 'escribir'. Pero algunas cosas dependen de '__iter__' y' readline' y otras características del archivo. ¿Cómo trato las cosas que quiero sin tener que volver a implementarlas? ¿O, mejor aún, el manejo especial de la nueva línea de Python para mis propios objetos similares a archivos? – Omnifarious

+0

Esta respuesta realmente no funciona para mí, ya que implica que tendré que volver a implementar una gran cantidad de funciones de 'archivo' (almacenamiento en búfer, manejo de nueva línea, líneas de lectura, writelines,' __enter__' y '__exit__' para su uso con' with', etc.) para todos y cada uno de los objetos similares a archivos que deseo implementar. ¿Hay alguna forma de evitar esto? – Omnifarious

+1

@Omnifarious: la respuesta es la respuesta. "Esta respuesta realmente no funciona para mí, ya que implica que tendré que volver a implementar una gran cantidad de funciones de archivos". Es irrelevante. Lástima que tengas que implementar todo. Eso no cambia la respuesta, ¿verdad? –

Cuestiones relacionadas