una quitar lista letras letra funciones especiales eliminar elementos como caracteres cadena borrar python stringio

quitar - funciones string python



¿Cómo borro un objeto de cadena? (3)

Tengo un objeto de stringio creado y tiene texto. Me gustaría borrar sus valores existentes y volver a utilizarlo en lugar de recordarlo. ¿Hay alguna forma de hacer esto?


TL; DR

No se moleste en despejarlo, solo cree uno nuevo, es más rápido.

El método

Python 2

Así es como encontraría tales cosas:

>>> from StringIO import StringIO >>> dir(StringIO) [''__doc__'', ''__init__'', ''__iter__'', ''__module__'', ''close'', ''flush'', ''getvalue'', ''isatty'', ''next'', ''read'', ''readline'', ''readlines'', ''seek'', ''tell'', ''truncate'', ''write'', ''writelines''] >>> help(StringIO.truncate) Help on method truncate in module StringIO: truncate(self, size=None) unbound StringIO.StringIO method Truncate the file''s size. If the optional size argument is present, the file is truncated to (at most) that size. The size defaults to the current position. The current file position is not changed unless the position is beyond the new file size. If the specified size exceeds the file''s current size, the file remains unchanged.

Entonces, quieres .truncate(0) . Pero probablemente sea más barato (y más fácil) inicializar un nuevo StringIO. Vea a continuación los puntos de referencia.

Python 3

(Gracias a tstone2077 por señalar la diferencia ).

>>> from io import StringIO >>> dir(StringIO) [''__class__'', ''__delattr__'', ''__dict__'', ''__dir__'', ''__doc__'', ''__enter__'', ''__eq__'', ''__exit__'', ''__format__'', ''__ge__'', ''__getattribute__'', ''__getstate__'', ''__gt__'', ''__hash__'', ''__init__'', ''__iter__'', ''__le__'', ''__lt__'', ''__ne__'', ''__new__'', ''__next__'', ''__reduce__'', ''__reduce_ex__'', ''__repr__'', ''__setattr__'', ''__setstate__'', ''__sizeof__'', ''__str__'', ''__subclasshook__'', ''_checkClosed'', ''_checkReadable'', ''_checkSeekable'', ''_checkWritable'', ''close'', ''closed'', ''detach'', ''encoding'', ''errors'', ''fileno'', ''flush'', ''getvalue'', ''isatty'', ''line_buffering'', ''newlines'', ''read'', ''readable'', ''readline'', ''readlines'', ''seek'', ''seekable'', ''tell'', ''truncate'', ''writable'', ''write'', ''writelines''] >>> help(StringIO.truncate) Help on method_descriptor: truncate(...) Truncate size to pos. The pos argument defaults to the current file position, as returned by tell(). The current file position is unchanged. Returns the new absolute position.

Es importante tener en cuenta que ahora la posición actual del archivo no se modifica , mientras que truncar al tamaño cero restablecería la posición en la variante de Python 2.

Por lo tanto, para Python 2, solo necesitas

>>> from cStringIO import StringIO >>> s = StringIO() >>> s.write(''foo'') >>> s.getvalue() ''foo'' >>> s.truncate(0) >>> s.getvalue() '''' >>> s.write(''bar'') >>> s.getvalue() ''bar''

Si haces esto en Python 3, no obtendrás el resultado esperado:

>>> from io import StringIO >>> s = StringIO() >>> s.write(''foo'') 3 >>> s.getvalue() ''foo'' >>> s.truncate(0) 0 >>> s.getvalue() '''' >>> s.write(''bar'') 3 >>> s.getvalue() ''/x00/x00/x00bar''

Entonces, en Python 3 también necesitas restablecer la posición:

>>> from cStringIO import StringIO >>> s = StringIO() >>> s.write(''foo'') 3 >>> s.getvalue() ''foo'' >>> s.truncate(0) 0 >>> s.seek(0) 0 >>> s.getvalue() '''' >>> s.write(''bar'') 3 >>> s.getvalue() ''bar''

Si usa el método truncate en el código Python 2, es más seguro llamar a seek(0) al mismo tiempo (antes o después, no importa) para que el código no se rompa cuando inevitablemente lo transporte a Python 3. ¡Y hay otra razón por la que debería crear un nuevo objeto StringIO !

Veces

Python 2

>>> from timeit import timeit >>> def truncate(sio): ... sio.truncate(0) ... return sio ... >>> def new(sio): ... return StringIO() ...

Cuando está vacío, con StringIO:

>>> from StringIO import StringIO >>> timeit(lambda: truncate(StringIO())) 3.5194039344787598 >>> timeit(lambda: new(StringIO())) 3.6533868312835693

Con 3KB de datos en, con StringIO:

>>> timeit(lambda: truncate(StringIO(''abc'' * 1000))) 4.3437709808349609 >>> timeit(lambda: new(StringIO(''abc'' * 1000))) 4.7179079055786133

Y lo mismo con cStringIO:

>>> from cStringIO import StringIO >>> timeit(lambda: truncate(StringIO())) 0.55461597442626953 >>> timeit(lambda: new(StringIO())) 0.51241087913513184 >>> timeit(lambda: truncate(StringIO(''abc'' * 1000))) 1.0958449840545654 >>> timeit(lambda: new(StringIO(''abc'' * 1000))) 0.98760509490966797

Por lo tanto, ignorando posibles problemas de memoria ( del oldstringio ), es más rápido truncar un StringIO.StringIO (3% más rápido para el vacío, 8% más rápido para 3KB de datos), pero es más rápido ("fasterer" también) para crear un nuevo cStringIO.StringIO (8% más rápido para vacío, 10% más rápido para 3KB de datos). Así que recomendaría simplemente usar el más fácil, suponiendo que esté trabajando con CPython, use cStringIO y cree otros nuevos.

Python 3

El mismo código, solo con seek(0) puesto.

>>> def truncate(sio): ... sio.truncate(0) ... sio.seek(0) ... return sio ... >>> def new(sio): ... return StringIO() ...

Cuando está vacío:

>>> from io import StringIO >>> timeit(lambda: truncate(StringIO())) 0.9706327870007954 >>> timeit(lambda: new(StringIO())) 0.8734330690022034

Con 3KB de datos en:

>>> timeit(lambda: truncate(StringIO(''abc'' * 1000))) 3.5271066290006274 >>> timeit(lambda: new(StringIO(''abc'' * 1000))) 3.3496507499985455

Así que para Python 3 crear uno nuevo en lugar de reutilizar uno en blanco es un 11% más rápido y crear uno nuevo en lugar de reutilizar uno de 3K es un 5% más rápido. Nuevamente, cree un nuevo StringIO lugar de truncar y buscar.


Cómo logré optimizar mi procesamiento (leer en fragmentos, procesar cada fragmento, escribir flujo procesado en un archivo) de muchos archivos en una secuencia es que reutilizo la misma instancia cStringIO.StringIO , pero siempre la reset() después de usarla, luego escribir en él, y luego truncate() . Al hacer esto, solo estoy truncando la parte al final que no necesito para el archivo actual. Esto parece haberme dado un ~ 3% de aumento en el rendimiento. Cualquiera que sea más experto en esto podría confirmar si esto efectivamente optimiza la asignación de memoria.

sio = cStringIO.StringIO() for file in files: read_file_chunks_and_write_to_sio(file, sio) sio.truncate() with open(''out.bla'', ''w'') as f: f.write(sio.getvalue()) sio.reset()


Hay algo importante a tener en cuenta (al menos con Python 3.2):

buscar (0) ES necesario antes de truncar (0). Aquí hay un código sin la búsqueda (0):

from io import StringIO s = StringIO() s.write(''1''*3) print(repr(s.getvalue())) s.truncate(0) print(repr(s.getvalue())) s.write(''1''*3) print(repr(s.getvalue()))

Qué salidas:

''111'' '''' ''/x00/x00/x00111''

con seek (0) antes del truncado, obtenemos el resultado esperado:

''111'' '''' ''111''