我正在尝试编写一个可以运行python 2&它从网站读取字符并写入文件。我已经从__future __。
导入了smallest
直接尝试编写一个如下所示的字符串:
unicode_literals
将导致UnicodeEncodeError:
txt = u'his$\u2026\n'
将它写入python2中的文件的唯一方法是:
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2026' in position 4: ordinal not in range(128)
但是,尝试在python3中重用相同的代码是不行的,因为在python 3中,
fp = open("/tmp/test", "w")
txt2 = txt.encode('utf-8')
fp.write(txt2) # It works
type(txt2) # str - that is why it works
E.g
type(txt2) # is byte type
强制txt.encode('utf-8')
b'his$\xe2\x80\xa6\n'
将抛出TypeError:
fp.write(txt2)
因此,可以在python 2和3中使用相同的代码块将TypeError: write() argument must be str, not bytes
写入文件中。(除了在fp.write上使用包装器)
答案 0 :(得分:7)
你说:
将它写入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
,但在某些情况下它非常慢),你可以使用较旧的方式,{{3} }:
fp = codecs.open("/tmp/test", "w", encoding='utf-8')
fp.write(txt2) # It works
两者之间存在差异,但您编写的大多数代码都不会对基础原始文件或编码器缓冲区或基本文件类对象API之外的任何其他内容感兴趣,所以你如果try
不可用,也可以使用except ImportError
/ codecs
回退到io
。
答案 1 :(得分:1)
使用'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