Chr*_*gan 90
不要打扰它,只需创建一个新的 - 它更快.
这是我如何找到这样的东西:
>>> 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.
Run Code Online (Sandbox Code Playgroud)
所以,你想要的.truncate(0).但初始化新的StringIO可能更便宜(也更容易).请参阅下面的基准测试.
(感谢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.
Run Code Online (Sandbox Code Playgroud)
重要的是要注意,现在当前文件位置不变,而截断到零大小将重置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'
Run Code Online (Sandbox Code Playgroud)
如果您在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'
Run Code Online (Sandbox Code Playgroud)
所以在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'
Run Code Online (Sandbox Code Playgroud)
如果truncate在Python 2代码中使用该方法,则同时调用seek(0)(之前或之后,无关紧要)更安全,这样当您不可避免地将代码移植到Python 3时代码不会中断.还有另一个原因你应该创建一个新StringIO对象!
>>> from timeit import timeit
>>> def truncate(sio):
... sio.truncate(0)
... return sio
...
>>> def new(sio):
... return StringIO()
...
Run Code Online (Sandbox Code Playgroud)
当为空时,使用StringIO:
>>> from StringIO import StringIO
>>> timeit(lambda: truncate(StringIO()))
3.5194039344787598
>>> timeit(lambda: new(StringIO()))
3.6533868312835693
Run Code Online (Sandbox Code Playgroud)
使用3个字符的数据,使用StringIO:
>>> timeit(lambda: truncate(StringIO('abc' * 1000)))
4.3437709808349609
>>> timeit(lambda: new(StringIO('abc' * 1000)))
4.7179079055786133
Run Code Online (Sandbox Code Playgroud)
和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
Run Code Online (Sandbox Code Playgroud)
因此,忽略潜在的内存问题(del oldstringio),截断a StringIO.StringIO(空3%快,3KB数据快8%)更快,但创建新的速度更快("紧固"也cStringIO.StringIO更快) 3KB数据快10%).所以我建议只使用最简单的一个 - 所以假设你正在使用CPython,使用cStringIO并创建新的.
相同的代码,只需seek(0)放入.
>>> def truncate(sio):
... sio.truncate(0)
... sio.seek(0)
... return sio
...
>>> def new(sio):
... return StringIO()
...
Run Code Online (Sandbox Code Playgroud)
空的时候:
>>> from io import StringIO
>>> timeit(lambda: truncate(StringIO()))
0.9706327870007954
>>> timeit(lambda: new(StringIO()))
0.8734330690022034
Run Code Online (Sandbox Code Playgroud)
有3KB的数据:
>>> timeit(lambda: truncate(StringIO('abc' * 1000)))
3.5271066290006274
>>> timeit(lambda: new(StringIO('abc' * 1000)))
3.3496507499985455
Run Code Online (Sandbox Code Playgroud)
因此,对于Python 3而言,创建一个新的而不是重用一个空白的那个快11%并且创建一个新的而不是重用3K的那个快5%.再次,创建一个新的StringIO而不是截断和寻求.
有一些重要的事情要注意(至少使用Python 3.2):
求(0)IS截断之前需要(0).这是一些没有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()))
Run Code Online (Sandbox Code Playgroud)
哪个输出:
'111'
''
'\x00\x00\x00111'
Run Code Online (Sandbox Code Playgroud)
在truncate之前使用seek(0),我们得到预期的输出:
'111'
''
'111'
Run Code Online (Sandbox Code Playgroud)