【问题标题】:Python StringIO.write doesn't like integer zero?Python StringIO.write 不喜欢整数零?
【发布时间】:2015-02-14 08:13:54
【问题描述】:

为什么 stream.write 几乎可以输出除零以外的任何东西?

from StringIO import StringIO
v0 = 0
v1 = 1
a = [1, 0, v1, v0, "string", 0.0, 2.0]
stream = StringIO()
for v in a:
    stream.write(v)
    stream.write('\n')
print stream.getvalue()

使用 Python 2.7.6,运行此代码会产生:

1

1

string

2.0

【问题讨论】:

  • 原来.write(0)StringIO 的上下文中表示don't write。我的猜测是,在其内部实现中,它可能首先检查输入,例如if 0:,它始终等于False。您是否有任何理由没有首先使用 str() 将项目转换为 string
  • 顺便说一句,我更喜欢使用cStringIO 而不是StringIO。它的速度更快。
  • 有趣的是,当v 不是字符串时,Python 3 io 模块(它替换了 StringIO 模块)会在stream.write(v) 上产生 TypeError。
  • 如 Python 2.7 中的 cStringIO.StringIO
  • @ozgur 实际上我确实最终用 str() 包装了数字,但很好奇为什么这应该是必要的。

标签: python stream stringio


【解决方案1】:

fileobj.write() 的接口要求你写一个字符串,总是:

file.write(str)
字符串写入文件。

强调我的。

这是一个实现细节,StringIO() 非字符串只是 发生 工作。使用代码optimises the 'empty string' case

if not s: return

避免进行不必要的字符串连接。这意味着如果您传入任何 falsey 值,例如数字 0 或 None 或空容器,则不会发生写入。

在写入之前将您的对象转换为字符串:

for v in a:
    stream.write(str(v))
    stream.write('\n')

如果您在此处使用 C 优化版本,您会遇到错误:

>>> from cStringIO import StringIO
>>> f = StringIO()
>>> f.write(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be string or buffer, not int

【讨论】:

  • 也许只是我,但“写一个字符串”是模棱两可的——它可以解释为“file.write 将输出一个字符串到文件”,而不是“你必须提供一个字符串作为输入”。
  • @PeterKrnjevic:方法的签名是file.write(str)。没有其他文件(类似)对象接受其他类型。
  • 看起来是这样。我尝试使用常规 file.write() 并且它按预期爆炸。但是,我有点惊讶像 Python 这样的动态语言在必要时不会“字符串化”类型。
  • @PeterKrnjevic:StringIO.write() 完全接受其他类型确实是一个早该删除的错误功能。新的 Python 3 I/O 基础结构(在 Python 2 中作为 io 模块提供)具有纠正错误的内存文件对象。
【解决方案2】:

好像在 StringIO.py 第 214 行(函数 write):

if not s: return

s 是您传递给write 的内容)。

换句话说,'falsy' 值(例如 None、[]、0 等)将被丢弃。

【讨论】:

  • 包含一个空字符串(这可能就是它存在的原因)
  • @cdarke,你为什么认为他们不能只传递空字符串?
  • @PeterKrnjevic 我不确定,但我猜这是为了避免不必要的对象创建,所以为了提高效率。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 2022-08-03
  • 2022-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多