首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何清除stringio对象?

如何清除stringio对象?
EN

Stack Overflow用户
提问于 2010-12-02 09:16:44
回答 3查看 42.5K关注 0票数 66

我创建了一个stringio对象,里面有一些文本。我想清除它的现有值并重用它,而不是调用它。有没有这样做的方法呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-12-02 09:20:16

TL;DR

不要费心清除它,只需创建一个新的-它会更快。

该方法

Python 2

下面是我如何找出这些事情的方法:

代码语言:javascript
复制
>>> 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可能更便宜(也更容易)。请参阅下面的基准。

Python 3

(感谢pointing out the differencetstone2077。)

代码语言:javascript
复制
>>> 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.

注意这一点很重要,因为现在当前文件位置是不变的,而截断到大小为零将重置Python 2变体中的位置。

因此,对于Python 2,您只需要

代码语言:javascript
复制
>>> 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中执行此操作,将不会得到预期的结果:

代码语言:javascript
复制
>>> 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中,您还需要重置位置:

代码语言:javascript
复制
>>> 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'

如果在Python2代码中使用truncate方法,则更安全的做法是同时调用seek(0) (在此之前或之后,这无关紧要),这样当您不可避免地将其移植到Python3时,代码就不会崩溃。还有另一个原因,您应该只创建一个新的StringIO对象!

《时代》

Python 2

代码语言:javascript
复制
>>> from timeit import timeit
>>> def truncate(sio):
...     sio.truncate(0)
...     return sio
... 
>>> def new(sio):
...     return StringIO()
... 

为空时,使用StringIO:

代码语言:javascript
复制
>>> from StringIO import StringIO
>>> timeit(lambda: truncate(StringIO()))
3.5194039344787598
>>> timeit(lambda: new(StringIO()))
3.6533868312835693

其中有3KB的数据,使用StringIO:

代码语言:javascript
复制
>>> timeit(lambda: truncate(StringIO('abc' * 1000)))
4.3437709808349609
>>> timeit(lambda: new(StringIO('abc' * 1000)))
4.7179079055786133

cStringIO也是如此:

代码语言:javascript
复制
>>> 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

因此,忽略潜在的内存问题(del oldstringio),截断StringIO.StringIO更快(空的快3%,3KB的数据快8% ),但创建新的cStringIO.StringIO更快(也更快)(空的快8%,3KB的数据快10% )。所以我建议只使用最简单的一个-所以假设你正在使用CPython,使用cStringIO并创建新的。

Python 3

相同的代码,只是加入了seek(0)

代码语言:javascript
复制
>>> def truncate(sio):
...     sio.truncate(0)
...     sio.seek(0)
...     return sio
... 
>>> def new(sio):
...     return StringIO()
...

为空时:

代码语言:javascript
复制
>>> from io import StringIO
>>> timeit(lambda: truncate(StringIO()))
0.9706327870007954
>>> timeit(lambda: new(StringIO()))
0.8734330690022034

其中包含3KB的数据:

代码语言:javascript
复制
>>> timeit(lambda: truncate(StringIO('abc' * 1000)))
3.5271066290006274
>>> timeit(lambda: new(StringIO('abc' * 1000)))
3.3496507499985455

所以对于Python3来说,创建一个新的而不是重用一个空的要快11%,创建一个新的而不是重用一个3K的要快5%。同样,创建一个新的StringIO,而不是截断和查找。

票数 112
EN

Stack Overflow用户

发布于 2013-04-23 11:55:08

有一些重要的事情需要注意(至少在Python 3.2中是这样):

在截断(0)之前需要seek(0) 。下面是一些不带seek(0)的代码:

代码语言:javascript
复制
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()))

以下哪项输出:

代码语言:javascript
复制
'111'
''
'\x00\x00\x00111'

在截断之前使用seek(0),我们得到预期的输出:

代码语言:javascript
复制
'111'
''
'111'
票数 13
EN

Stack Overflow用户

发布于 2012-03-23 08:28:07

我如何设法优化对多个文件的顺序处理(读入块,处理每个块,将处理过的流写出到文件)的方法是重用相同的cStringIO.StringIO实例,但总是在使用之后对其执行reset()操作,然后写入它,然后执行truncate()。通过这样做,我只截断了当前文件末尾不需要的部分。这似乎给我带来了大约3%的性能提升。任何在这方面更专业的人都可以确认这是否真的优化了内存分配。

代码语言:javascript
复制
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()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4330812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档