【问题标题】:How to write unicode text to file in python 2 & 3 using same code?如何使用相同的代码将 unicode 文本写入 python 2 和 3 中的文件?
【发布时间】:2018-09-17 01:30:00
【问题描述】:

我正在尝试编写一个可以通过 python 2 和 3 运行的程序。它从网站读取字符并写入文件。我已经从 __future__ 导入了unicode_literals

直接尝试编写如下所示的字符串:

txt = u'his$\u2026\n'

会导致UnicodeEncodeError:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2026' in position 4: ordinal not in range(128)

在python2中将其写入文件的唯一方法是:

fp = open("/tmp/test", "w")
txt2 = txt.encode('utf-8')
fp.write(txt2) # It works
type(txt2) # str - that is why it works

但是,尝试在 python3 中重用相同的代码是行不通的,因为在 python 3 中,

type(txt2) # is byte type

例如

txt.encode('utf-8')
b'his$\xe2\x80\xa6\n'

强制 fp.write(txt2) 会抛出 TypeError:

TypeError: write() argument must be str, not bytes

所以,可以在 python 2 和 3 中使用相同的代码块将txt = u'his$\u2026\n' 写入文件中。(除了在 fp.write 上使用包装器)

【问题讨论】:

  • 使用 'print(txt.encode('utf-8'), file=fp)` 是兼职解决方案。它将在 python2 中运行良好。但是,它在 python3 中运行得不够好,它不会打印实际字符,而是实际打印字节的字符串文字表示。如,而不是打印 his$... python3 将结束: b'his$\xe2\x80\xa6\n'。
  • “混合字符串”是什么意思?我看到你已经标记了这个 unicode-normalization;这是一个问题吗?
  • 我不应该说混合字符串,我的错。打印时的字符串如下所示:his$...

标签: python python-unicode python-2to3


【解决方案1】:

你说:

在python2中将其写入文件的唯一方法是:

fp = open("/tmp/test", "w")
txt2 = txt.encode('utf-8')
fp.write(txt2) # It works

但事实并非如此。有很多比这更好的方法。一个明显的方法是使用io.open。在 3.x 中,这与内置 open 的功能相同。在 2.6 和 2.7 中,它实际上是 3.x 内置的后向移植。这意味着您可以在两个版本中获得 3.x 样式的 Unicode 文本文件:

fp = io.open("/tmp/test", "w", encoding='utf-8')
fp.write(txt2) # It works

如果您需要兼容 2.5 或更早版本——或者可能是 2.6 和 3.0(它们支持 io.open,但在某些情况下速度很慢),您可以使用旧的方式,codecs.open

fp = codecs.open("/tmp/test", "w", encoding='utf-8')
fp.write(txt2) # It works

两者之间存在本质上的差异,但是您编写的大多数代码不会对底层原始文件或编码器缓冲区或除基本的类文件对象 API 之外的任何其他内容感兴趣,因此您也可以如果io 不可用,请使用try/except ImportError 回退到codecs

【讨论】:

  • codecs.open 解决了我的问题。我忽略了 io.open,因为它在 2.6 中太慢了,并且除了编码/解码之外没有太多的编解码器。我将此标记为已解决。谢谢。
【解决方案2】:

使用'b' 模式打开文件将允许您在 Python2 和 Python3 中使用相同的代码:

txt = u'his$\u2026\n'

with open("/tmp/test", "wb") as fp:
    fp.write(txt.encode('utf-8'))

结果:

$ python2 x.py 
$ md5sum /tmp/test
f39cd7554a823b05658d776a27eb97d9  /tmp/test
$ python3 x.py 
$ md5sum /tmp/test
f39cd7554a823b05658d776a27eb97d9  /tmp/test

【讨论】:

    猜你喜欢
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    • 2020-10-19
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    相关资源
    最近更新 更多