TL; DR
Не пытайтесь очистить его, просто создайте новый - он быстрее.
Метод
Python 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.Ниже приведены тесты.
Python 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.
Важно отметить, что теперь текущая позиция файла не изменяется , тогда как усечение до нулевого размера приведет к сбросу позиции в варианте 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'
Если в коде Python 2 используется метод truncate
, безопаснее одновременно вызывать seek(0)
(до или после, это не имеет значения), чтобы код победил 'не работает, когда вы неизбежно портируете его на Python 3. И есть еще одна причина, почему вы должны просто создать новый StringIO
объект!
Times
Python 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
И то же самоеith 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
Итак, игнорируя потенциальные проблемы с памятью (del oldstringio
), быстрее усечь StringIO.StringIO
(на 3% быстрее для пустых, на 8% быстрее для 3 КБ данных), но этобыстрее (также «быстрее») для создания нового cStringIO.StringIO
(на 8% быстрее для пустых, на 10% быстрее для 3 КБ данных).Поэтому я бы порекомендовал использовать самый простой - предположим, что вы работаете с CPython, используйте cStringIO
и создайте новые.
Python 3
Тот же код, только с seek(0)
вставлено.
>>> def truncate(sio):
... sio.truncate(0)
... sio.seek(0)
... return sio
...
>>> def new(sio):
... return StringIO()
...
Когда пусто:
>>> from io import StringIO
>>> timeit(lambda: truncate(StringIO()))
0.9706327870007954
>>> timeit(lambda: new(StringIO()))
0.8734330690022034
С 3KB данных в:
>>> timeit(lambda: truncate(StringIO('abc' * 1000)))
3.5271066290006274
>>> timeit(lambda: new(StringIO('abc' * 1000)))
3.3496507499985455
Так что для Python 3 вместо этого создайте новыйповторное использование пустого - на 11% быстрее, а создание нового вместо повторного использования 3K - на 5% быстрее.Опять же, создайте новый StringIO
вместо усечения и поиска.