2012-09-25 7 views
13

Si una función toma como entrada el nombre de un archivo de texto, puedo refactorizarlo para tomar un objeto de archivo (lo llamo "secuencia"; ¿hay una palabra mejor?) Las ventajas son obvias - una función que toma una corriente como un argumento es:nombre de archivo vs objeto de archivo como argumento de función

  • mucho más fácil escribir una prueba unitaria para, ya no necesito para crear un archivo temporal sólo para la prueba
  • más flexible, ya que puedo usarlo en situaciones donde de alguna manera ya tengo el contenido del archivo en una variable

¿Hay alguna desventaja en las transmisiones? ¿O debería siempre refactorizar una función desde un argumento de nombre de archivo a un argumento de transmisión (suponiendo, por supuesto, que el archivo sea solo de texto)?

Respuesta

4

Existen numerosas funciones en la biblioteca estándar de python que aceptan ambas cadenas de caracteres, que son nombres de archivo u objetos de archivo abierto (supongo que es a eso a lo que se refiere como una "secuencia"). Realmente no es difícil crear un decorador que pueda usar para que sus funciones acepten cualquiera de los dos.

Una de las desventajas del uso de "transmisiones" es que lo pasa a su función y luego su función lee desde allí, cambiando efectivamente su estado. Dependiendo de su programa, recuperar ese estado podría ser complicado si fuera necesario. (Por ejemplo, es posible que necesite la basura se codifican con f.tell() y luego f.seek().)

+0

Sí, cuando dije "secuencia", quise decir "objeto de archivo abierto". ¿No sería posible escribir un decorador que guarde y restaure el estado de la secuencia? – max

+0

¿Y no hay una manera de crear una copia barata de una secuencia, de modo que la copia posea su propio "puntero", mientras que el "puntero" de la secuencia original queda intacto? Eso sería incluso más limpio que el método de guardar/restaurar estado. – max

+0

@max - Claro, podrías escribir un decorador para hacer eso. Lo importante es documentar cuándo está restaurando el estado y cuándo no. En cuanto a la creación de una copia, lo único que se me ocurre es 'itertools.tee', que es un poco diferente (pero es mucho más allá de mi hora de acostarse normal, así que no garantizo nada de lo que escribo ahora mismo: ^). – mgilson

5

... Aquí es cómo xml.etree.ElementTree módulo implementa la función parse:

def parse(self, source, parser=None): 
    close_source = False 
    if not hasattr(source, "read"): 
     source = open(source, "rb") 
     close_source = True 
    ... 

Como nombre de archivo es una cadena, no tiene el método read() (aquí cualquier atributo de ese nombre está marcado); sin embargo, el archivo abierto lo tiene. Las cuatro líneas hacen que el resto del código sea común. La única complicación es que debe recordar si cerrar el objeto de archivo (aquí se llama source) o no. Si fue open adentro, entonces debe estar cerrado. De lo contrario, no debe estar cerrado.

En realidad, los archivos difieren de las sonrisas levemente. Los flujos son potencialmente infinitos, mientras que los archivos generalmente no (a menos que algún dispositivo esté mapeado como si fuera un archivo). La diferencia importante cuando se procesa es que nunca se puede leer la secuencia en la memoria a la vez. Tienes que procesarlo en trozos.

+0

Estaba buscando una implementación de referencia sobre esto en el archivo stdlib. Gracias por el fragmento realmente ahorra tiempo. Le daría otro +1 por la advertencia de trozos si pudiera. – n611x007

Cuestiones relacionadas