Jam*_*s T 3 python python-2to3 python-unicode
我正在尝试编写一个可以运行python 2和3的程序.它从网站读取字符并写入文件.我已经unicode_literals从__future__ 导入了.
直接尝试写一个看起来像这样的字符串:
txt = u'his$\u2026\n'
Run Code Online (Sandbox Code Playgroud)
会导致UnicodeEncodeError:
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2026' in position 4: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
将它写入python2中的文件的唯一方法是:
fp = open("/tmp/test", "w")
txt2 = txt.encode('utf-8')
fp.write(txt2) # It works
type(txt2) # str - that is why it works
Run Code Online (Sandbox Code Playgroud)
但是,尝试在python3中重用相同的代码是不行的,因为在python 3中,
type(txt2) # is byte type
Run Code Online (Sandbox Code Playgroud)
例如
txt.encode('utf-8')
b'his$\xe2\x80\xa6\n'
Run Code Online (Sandbox Code Playgroud)
强制a fp.write(txt2)会抛出TypeError:
TypeError: write() argument must be str, not bytes
Run Code Online (Sandbox Code Playgroud)
因此,可以txt = u'his$\u2026\n'在python 2和3中使用相同的代码块写入文件中.(除了在fp.write上使用包装器)
你说:
将它写入python2中的文件的唯一方法是:
fp = open("/tmp/test", "w")
txt2 = txt.encode('utf-8')
fp.write(txt2) # It works
Run Code Online (Sandbox Code Playgroud)
但事实并非如此.有很多方法比这更好.一个明显的方法是做到这一点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
Run Code Online (Sandbox Code Playgroud)
如果你需要兼容2.5或更早版本 - 或者可能是2.6和3.0(它们支持io.open,但在某些情况下它很慢),你可以使用旧版本,codecs.open:
fp = codecs.open("/tmp/test", "w", encoding='utf-8')
fp.write(txt2) # It works
Run Code Online (Sandbox Code Playgroud)
两者之间存在差异,但是您编写的大多数代码不会对基础原始文件或编码器缓冲区或基本文件类对象API之外的任何其他内容感兴趣,因此您也可以使用try/ except ImportError来codecs如果io不可用则回归.