TypeError:write()参数1必须是unicode,而不是str

Ana*_*ira 5 python urllib2 python-2.7 python-unicode

我正在尝试导入文本文件并将其保存在桌面上,但是文本位于“ 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
Run Code Online (Sandbox Code Playgroud)

代码:

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()
Run Code Online (Sandbox Code Playgroud)

如何使用utf-8编码保存此文件?我在Python 2.7中使用Pycharm

Sha*_*ger 7

您的问题是urlopen返回一个面向字节的类似文件的对象,同时要求io.open输入真正的文本(其中“ text” unicode在Python 2 str上表示“ 在Python 3上”)。

您唯一需要更改的就是decode调用结果read;默认情况下,它类似于字节,并且您需要真实的文本。您需要找出正确的编码(对它进行硬编码,或显式检查标题以弄清楚)才能正确地对其进行解码(可能是UTF-8或更少的cp1252,但这可能很奇怪)。

无论如何,知道这一点,您唯一需要做的更改就是更改:

libro.write(archivo.read())
Run Code Online (Sandbox Code Playgroud)

至:

libro.write(archivo.read().decode(knownencoding))
Run Code Online (Sandbox Code Playgroud)

如果您确定服务器始终提供UTF-8输出,则:

libro.write(archivo.read().decode('utf-8'))
Run Code Online (Sandbox Code Playgroud)

足够了。是的,这非常浪费(您仅将其解码以将其写入立即重新编码的流中即可),但是重要的是,这可以确保您将接收到的字节解释为有效的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)
Run Code Online (Sandbox Code Playgroud)