python3 - ¿Para qué sirve StringIO en python en realidad?
stringio ruby (7)
No soy un profesional y me he estado rascando la cabeza por entender para qué se usa exactamente StringIO. He estado buscando en internet algunos ejemplos. Sin embargo, casi todos los ejemplos son muy abstractos. Y solo muestran "cómo" usarlo. ¿Pero ninguno de ellos muestra "por qué" y "en qué circunstancias" uno debería usarlo? Gracias por adelantado
ps no debe confundirse con esta pregunta en stackoverflow: uso de StringIO que compara cadena y StringIo.
Acabo de utilizar StringIO en la práctica por dos cosas:
- Para probar la unidad de una secuencia de comandos que hace una gran cantidad de
print
, al redirigirsys.stdout
a una instancia deStringIO
para un fácil análisis; - Para crear un documento XML bien formado y garantizado (una solicitud API personalizada) usando
ElementTree
y luegowrite
para enviarlo a través de una conexión HTTP.
No es que necesite StringIO
menudo , pero a veces es bastante útil.
Django tiene una función call_command
que se utiliza para llamar a los comandos de gestión. Esta función imprime la salida en stdout y no devuelve ningún valor. Si desea saber si el comando se ejecutó correctamente o no, debe buscar el resultado y decidir.
Usando StringIO, puede capturar la salida y verificar si se desea o no la salida.
with io.StringIO() as output:
call_command(''custom_command'', stdout=output)
if ''Success'' not in output.getvalue():
print(''Custom command failed...'')
En los casos en los que desea un objeto similar a un archivo que ACTÚEA como un archivo, pero está escribiendo en un búfer de cadena en memoria: StringIO es la herramienta. Si está creando cadenas de gran tamaño, como documentos de texto sin formato y haciendo una gran cantidad de concatenación de cadenas, puede que le resulte más fácil simplemente usar StringIO en lugar de mystr += ''more stuff/n''
operaciones de tipo mystr += ''more stuff/n''
.
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 here :
Una secuencia en memoria para E / S de texto. El buffer de texto se descarta cuando se llama al método close ().
El valor inicial del buffer puede establecerse proporcionando initial_value.
método getvalue (): devuelve un str que contiene todo el contenido del buffer.
Se usa cuando tienes una 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 similar a un archivo a las cadenas, por lo que puede usar un módulo existente que se ocupa de un archivo y no cambia casi nada y lo hace funcionar con cadenas.
Por ejemplo, supongamos que tiene un registrador que escribe cosas en un archivo y, en su lugar, desea enviar el resultado de 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 manera.
Un par de cosas que personalmente he usado para:
Almacenamiento en caché de archivos completos. Tengo un script que lee archivos PDF y hace validaciones de varias cosas sobre ellos. La biblioteca PDF que estoy utilizando toma un archivo abierto en su constructor de documento. Originalmente abrí el PDF que estaba interesado en leer, sin embargo, cuando lo cambié para leer todo el archivo a la vez en la memoria y luego pasé un objeto StringIO a la biblioteca PDF, el tiempo de ejecución de mi script se redujo a la mitad.
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 ignorar ciertas pruebas que están en su archivo de configuración o solo incluir algunas. Si ignoro todas las pruebas para un PDF determinado, no quiero que se imprima el encabezado, pero no sabré cuántas pruebas realicé hasta que termine de ejecutar las pruebas (las pruebas también pueden definirse dinámicamente). Así que capturo el encabezado en un objeto StringIO cambiando
sys.stdout
para que apunte a él, y cada vez que ejecuto una prueba, compruebo si ese objeto tiene algo. Si es así, lo imprimo y lo reinicio en vacío. Voila, solo los PDF que tienen pruebas tienen encabezados impresos.