【问题标题】:unicode_literals and StringIO and the right way to do thingsunicode_literals 和 StringIO 以及正确的做事方式
【发布时间】:2016-01-29 09:29:31
【问题描述】:

是的,另一个漫无边际的 unicode 问题。

我有一个代码sn-p:

from __future__ import unicode_literals
import requests
from lxml import etree

class Review(object):
    def __init__(self, site_name):
        self.parser = etree.HTMLParser()
        # other things

     def get_root(self, url):
        # snip snip
        resp = requests.get(url)
        html = resp.text
        root = etree.parse(StringIO(html), self.parser)
        return root

这行得通。

在 Python 3 中,这将类似于:

from urllib import request
# stuff to detect encoding of page
response = request.urlopen(req)
html = response.read().decode(detected_encoding)
root = etree.parse(StringIO(self.html_doc), self.parser)

当页面声明的编码不是其实际编码时,需要处理大量丑陋的代码。

我的问题是 unicode_literals 对我来说本质上是巫术,我为自己的无知感到尴尬。为什么root = etree.parse(StringIO(html), self.parser)大多数中在导入 unicode_literals 的情况下神奇地工作,在 python 2.7 中真正正确的做法是什么?

例如,我现在正在修复的一些 Django 代码中有这个结构:

stuff = StringIO(unicode(request.body))

那是不好的和错误的。但我无法解释为什么它是坏的和错误的,只能说它破坏了 not utf-8

许多 编码

我知道字符串是在 python 3 中编码的字符串,在 python 2.7 中是 ascii。我知道 StringIO 让我将字符串视为缓冲区。而且我知道stuff = StringIO(unicode(request.body)) 可以使用导入的 unicode_literals request.body,这就是我发布此内容的原因。

tl;博士

python 2.7 中的 unicode_literals 是什么,它会修复 stuff = StringIO(unicode(request.body)) 中的 Django 错误,会有什么副作用?

非常感谢

【问题讨论】:

  • 您的基本误解是 Python 3 中的字符串是“带编码的字符串”。不,字符串是 unicode,并且没有编码。

标签: python django python-2.7 unicode


【解决方案1】:

unicode 文字不会影响StringIO(unicode(request.body)) 之类的代码。它所做的只是在 Python 2 中不使用前缀时更改文字字符串的类型。

没有 unicode 文字

u'y'  # unicode string
b'z'  # byte string
'x'  # byte string

使用 unicode 文字

from __future__ import unicode_literals
u'y'  # unicode string
b'z'  # byte string
'x'  # *unicode* string

当您使用 unicode 文字时,您的行为与 Python 3.3+ 相同(您不能在 Python 3.0 到 3.2 中使用 u'')。

request.body从字节串转换为unicode字符串的正确方法是在从字节串转换为unicode时指定编码。

stuff = StringIO(body.decode('utf-8'))

如果编码不是utf-8,则更改编码。

【讨论】:

  • 谢谢回复,更清楚了。如果 body.decode 抛出和 UnicodeDecode 错误怎么办?我是否继续尝试其他编码?
  • 理想情况下,您应该知道编码,而不必尝试多种编码。如果你使用requestsresp = requests.get(url),那么你应该可以得到resp.encoding 的编码。如果您不知道编码,那么我不确定解码字节串的最佳方法是什么。如果您只是尝试不同的编码直到其中一种有效,那么您可能会收到静默错误。
  • 在这种情况下,请求来自某个 API 端点,我无法控制客户端应用程序的编码是什么。
猜你喜欢
  • 2018-11-12
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多