我正在尝试导入一个文本文件并将其保存在我的桌面上,但文本是“utf-8”(书中有这个信息),所以当我保存没有编码时,文本有很多奇怪的字符,但是当我尝试使用显式编码保存此错误:
Traceback (most recent call last): File "C:/Users/Unidas/Semestre/ABC/8.1.py", line 14, in n_palabras libro.write(archivo.read()) TypeError: write() argument 1 must be unicode, not str
代码:
def n_palabras(x):
import urllib2
import io
import string
archivo = urllib2.urlopen(x)
libro = io.open("alice.txt", "w", encoding="utf8")
libro.write(archivo.read())
libro.close()
如何使用utf-8编码保存此文件?我在Python 2.7中使用Pycharm
你的问题是urlopen
返回一个面向字节的文件类对象,而io.open
则需要真正的文本输入(其中“text”表示“Python 2上的unicode
,Python 3上的str
”)。
你唯一需要改变的是decode
调用read
的结果;它默认为字节,你需要真正的文本。你需要找出正确的编码(硬编码,或明确检查标头来弄清楚它)才能正确解码(它可能是UTF-8,或者更不可能是cp1252,但它可能是奇怪的东西)。
无论如何,知道这一点,你需要做的唯一改变就是改变:
libro.write(archivo.read())
至:
libro.write(archivo.read().decode(knownencoding))
如果您非常确定服务器始终提供UTF-8输出,那么:
libro.write(archivo.read().decode('utf-8'))
足够了。是的,它有点浪费(你解码它只是为了将它写入一个立即重新编码它的流),但重要的是,这可以保证你收到的字节可以解释为有效的UTF-8,它将原始字节转储到磁盘不保证。
一个更精细的解决方案检查标题:
import urllib2
import io
import string
def n_palabras(x):
archivo = urllib2.urlopen(x)
# Find charset in headers, if it exists
for p in archivo.headers.plist:
key, sep, value = p.partition('=')
if sep and key.strip().lower() == 'charset':
encoding = value.strip()
break
else:
encoding = 'utf-8'
data = archivo.read()
try:
# Try to use parsed charset
data = data.decode(encoding)
except UnicodeDecodeError:
# If that fails, try UTF-8 as fallback; let exception bubble
# if this fails too
data = data.decode('utf-8')
with io.open("alice.txt", "w", encoding="utf-8") as libro:
libro.write(data)