¿Para qué se utiliza StringIO en Python en realidad?

No soy un profesional y me he estado rascando la cabeza al entender para qué se utiliza exactamente StringIO. He estado buscando en internet algunos ejemplos. Sin embargo, casi todos los ejemplos son muy abstractos. Y simplemente muestran “cómo” usarlo. Pero ninguno de ellos muestra “por qué” y “en qué circunstancias” uno debería / lo usará? Gracias por adelantado

ps no debe confundirse con esta pregunta en stackoverflow: StringIO Uso que compara cadena y StringIo.

Se usa cuando tienes alguna API que solo toma archivos, pero necesitas usar una cadena. Por ejemplo, para comprimir una cadena usando el módulo gzip en Python 2:

import gzip import StringIO stringio = StringIO.StringIO() gzip_file = gzip.GzipFile(fileobj=stringio, mode='w') gzip_file.write('Hello World') gzip_file.close() stringio.getvalue() 

StringIO le brinda acceso a cadenas a modo de archivo, por lo que puede usar un módulo existente que se ocupa de un archivo y no cambiar casi nada y hacer que funcione con cadenas.

Por ejemplo, supongamos que tiene un registrador que escribe cosas en un archivo y en su lugar desea enviar la salida del registro a través de la red. Puede leer el archivo y escribir su contenido en la red, o puede escribir el registro en un objeto StringIO y enviarlo a su destino de red sin tocar el sistema de archivos. StringIO hace que sea fácil hacerlo de la primera manera y luego cambiar a la segunda.

En los casos en los que desea un objeto similar a un archivo que ACTS tiene gusto de un archivo, pero está escribiendo en un búfer de cadena en memoria: StringIO es la herramienta. Si está creando cadenas grandes, como documentos de texto sin formato, y haciendo mucha concatenación de cadenas, puede que le resulte más fácil usar StringIO en lugar de un montón de mystr += 'more stuff\n' .

Acabo de usar StringIO en la práctica para dos cosas:

  • Para realizar una prueba unitaria de un script que hace mucha print , redireccionando sys.stdout a una instancia de StringIO para un análisis fácil;
  • Para crear un documento XML bien formado garantizado (una solicitud de API personalizada) utilizando ElementTree y luego write para enviarlo a través de una conexión HTTP.

No es que necesites StringIO menudo , pero a veces es bastante útil.

Un par de cosas que personalmente lo he usado para:

  1. Caché de archivo completo. Tengo un script que lee archivos PDF y hace validación de varias cosas sobre ellos. La biblioteca de PDF que estoy usando toma un archivo abierto en su constructor de documentos. Originalmente, acabo de abrir el PDF que estaba interesado en leer, sin embargo, cuando lo cambié para leer todo el archivo de una vez en la memoria y luego pasar un objeto StringIO a la biblioteca de PDF, el tiempo de ejecución de mi script se redujo a la mitad.

  2. Impresión diferida. El mismo script imprime un encabezado antes de cada PDF que lee. Sin embargo, puedo especificar en la línea de comandos si se deben ignorar ciertas pruebas que se encuentran en su archivo de configuración o si solo se incluyen ciertas. Si ignoro todas las pruebas para un PDF determinado, no quiero que se imprima el encabezado, pero no sabré cuántas pruebas ejecuté hasta que termine de ejecutarlas (las pruebas también se pueden definir dinámicamente). Así que capturo el encabezado en un objeto StringIO cambiando sys.stdout para señalarlo, y cada vez que ejecuto una prueba sys.stdout si ese objeto tiene algo en él. Si es así, lo imprimo y luego lo restablezco a vacío. Voila, solo los PDF que tienen pruebas tienen encabezados impresos.

Django tiene una función call_command que se usa para llamar comandos de administración. Esta función imprime la salida en la salida estándar y no devuelve ningún valor. Si desea saber si el comando se ejecutó con éxito o no, debe buscar en la salida y decidir.

Utilizando StringIO, puede capturar la salida y verificar si se desea o no la salida deseada.

 with io.StringIO() as output: call_command('custom_command', stdout=output) if 'Success' not in output.getvalue(): print('Custom command failed...') 

Lo he usado en lugar de archivos de texto para pruebas de unidad.

Por ejemplo, para hacer un ‘archivo’ csv para probar con pandas (Python 3):

 import io f = io.StringIO("id,name\n1,brian\n2,amanda\n3,zoey\n") df = pd.read_csv(f) # pandas takes a file path or a file-like object 

De la documentación aquí :

Un flujo en memoria para la E / S de texto. El búfer de texto se descarta cuando se llama al método close ().

El valor inicial del búfer se puede establecer proporcionando initial_value.

método getvalue (): devuelve una cadena que contiene todo el contenido del búfer.