programing

stringio 객체를 어떻게 지우나요?

kingscode 2021. 1. 14. 22:55
반응형

stringio 객체를 어떻게 지우나요?


stringio 개체가 생성되었으며 일부 텍스트가 있습니다. 기존 값을 지우고 다시 불러오는 대신 재사용하고 싶습니다. 어쨌든 이런 일이 있습니까?


TL; DR

지우지 말고 새로 만드십시오. 더 빠릅니다.

방법

파이썬 2

내가 그런 것들을 찾는 방법은 다음과 같습니다.

>>> 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.

그래서 당신은 .truncate(0). 그러나 새 StringIO를 초기화하는 것이 더 저렴하고 더 쉽습니다. 벤치 마크는 아래를 참조하십시오.

파이썬 3

( 차이점지적 해 주신 tstone2077 에게 감사드립니다 .)

>>> 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.

현재 파일 위치는 변경되지 않은 반면 크기를 0으로 자르면 Python 2 변형의 위치가 재설정 된다는 점에 유의하는 것이 중요합니다 .

따라서 Python 2의 경우

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

Python 3에서이 작업을 수행하면 예상 한 결과를 얻지 못할 것입니다.

>>> 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'

따라서 Python 3에서는 위치를 재설정해야합니다.

>>> 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'

truncatePython 2 코드에서 메서드를 사용하는 경우 seek(0), 필연적으로 Python 3으로 이식 할 때 코드가 깨지지 않도록 동시에 호출하는 것이 더 안전합니다 (이전 또는 이후에 상관 없음). 그리고 또 다른 이유가 있습니다. 새 StringIO개체를 만들어야 합니다!

타임스

파이썬 2

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

비어있는 경우 StringIO 사용 :

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

3KB의 데이터 입력, StringIO 사용 :

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

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

So, ignoring potential memory concerns (del oldstringio), it's faster to truncate a StringIO.StringIO (3% faster for empty, 8% faster for 3KB of data), but it's faster ("fasterer" too) to create a new cStringIO.StringIO (8% faster for empty, 10% faster for 3KB of data). So I'd recommend just using the easiest one—so presuming you're working with CPython, use cStringIO and create new ones.

Python 3

The same code, just with seek(0) put in.

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

When empty:

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

With 3KB of data in:

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

So for Python 3 creating a new one instead of reusing a blank one is 11% faster and creating a new one instead of reusing a 3K one is 5% faster. Again, create a new StringIO rather than truncating and seeking.


There is something important to note (at least with Python 3.2):

seek(0) IS needed before truncate(0). Here is some code without the seek(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()))

Which outputs:

'111'
''
'\x00\x00\x00111'

with seek(0) before the truncate, we get the expected output:

'111'
''
'111'

How I managed to optimise my processing (read in chunks, process each chunk, write processed stream out to file) of many files in a sequence is that I reuse the same cStringIO.StringIO instance, but always reset() it after using, then write to it, and then truncate(). By doing this, I'm only truncating the part at the end that I don't need for the current file. This seems to have given me a ~3% performance increase. Anybody who's more expert on this could confirm if this indeed optimises memory allocation.

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()

ReferenceURL : https://stackoverflow.com/questions/4330812/how-do-i-clear-a-stringio-object

반응형