manager context python with-statement contextmanager

python - manager - StringIO y compatibilidad con la declaración ''with''(administrador de contexto)



context manager python (2)

Tengo algún código heredado con una función heredada que toma un nombre de archivo como argumento y procesa el contenido del archivo. Un facsímil de trabajo del código está debajo.

Lo que quiero hacer es no tener que escribir en el disco con algún contenido que genere para usar esta función heredada, así que pensé que podría usar StringIO para crear un objeto en lugar del nombre de archivo físico. Sin embargo, esto no funciona, como puedes ver a continuación.

Pensé que StringIO era el camino a seguir con esto. ¿Alguien puede decirme si hay una forma de usar esta función heredada y pasarle algo en el argumento de que no es un archivo en el disco pero que puede ser tratado como tal por la función heredada? La función heredada tiene el gestor de contexto trabajando en el valor del parámetro de filename .

La única cosa que encontré en google fue: http://bugs.python.org/issue1286 , pero eso no me ayudó ...

Código

from pprint import pprint import StringIO # Legacy Function def processFile(filename): with open(filename, ''r'') as fh: return fh.readlines() # This works print ''This is the output of FileOnDisk.txt'' pprint(processFile(''c:/temp/FileOnDisk.txt'')) print # This fails plink_data = StringIO.StringIO(''StringIO data.'') print ''This is the error.'' pprint(processFile(plink_data))

Salida

Este es el resultado en FileOnDisk.txt :

[''This file is on disk./n'']

Este es el error:

Traceback (most recent call last): File "C:/temp/test.py", line 20, in <module> pprint(processFile(plink_data)) File "C:/temp/test.py", line 6, in processFile with open(filename, ''r'') as fh: TypeError: coercing to Unicode: need string or buffer, instance found


Una instancia de StringIO es un archivo abierto ya. El comando open , por otro lado, solo toma los nombres de archivo, para devolver un archivo abierto. Una instancia de StringIO no es adecuada como nombre de archivo.

Además, no es necesario cerrar una instancia de StringIO , por lo que tampoco es necesario utilizarla como gestor de contexto.

Si todo su código heredado puede tomar es un nombre de archivo, entonces una instancia de StringIO no es el camino a seguir. Use el módulo tempfile para generar un nombre de archivo temporal en su lugar.

Aquí hay un ejemplo que usa un gestor de contexto para asegurar que el archivo temporal se limpie después:

import os import tempfile from contextlib import contextmanager @contextmanager def tempinput(data): temp = tempfile.NamedTemporaryFile(delete=False) temp.write(data) temp.close() try: yield temp.name finally: os.unlink(temp.name) with tempinput(''Some data./nSome more data.'') as tempfilename: processFile(tempfilename)


podrías definir tu propia función abierta

fopen = open def open(fname,mode): if hasattr(fname,"readlines"): return fname else: return fopen(fname,mode)

sin embargo, con quiere llamar a __exit__ una vez hecho esto y StringIO no tiene un método de salida ...

puedes definir una clase personalizada para usar con este abrir

class MyStringIO: def __init__(self,txt): self.text = txt def readlines(self): return self.text.splitlines() def __exit__(self): pass