当前位置:  开发笔记 > 编程语言 > 正文

在Python 2.6中使用unicode_literals的任何陷阱?

如何解决《在Python2.6中使用unicode_literals的任何陷阱?》经验,为你挑选了5个好方法。

我们已经在Python 2.6下运行了我们的代码库.为了准备Python 3.0,我们开始添加:

from __future__ import unicode_literals

进入我们的.py文件(因为我们修改它们).我想知道是否还有其他人这样做并遇到任何非显而易见的陷阱(也许是在花了很多时间调试之后).



1> Koba..:

我使用unicode字符串的主要问题是你将utf-8编码的字符串与unicode字符串混合在一起.

例如,请考虑以下脚本.

two.py

# encoding: utf-8
name = 'helló wörld from two'

one.py

# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name

运行的输出python one.py是:

Traceback (most recent call last):
  File "one.py", line 5, in 
    print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)

在这个例子中,two.name是一个utf-8编码的字符串(不是unicode),因为它没有导入unicode_literals,并且one.name是一个unicode字符串.当你混合两者时,python尝试解码编码的字符串(假设它是ascii)并将其转换为unicode并失败.如果你这样做会有用print name + two.name.decode('utf-8').

如果您对字符串进行编码并尝试稍后混合它们,则会发生同样的情况.例如,这有效:

# encoding: utf-8
html = 'helló wörld'
if isinstance(html, unicode):
    html = html.encode('utf-8')
print 'DEBUG: %s' % html

输出:

DEBUG: helló wörld

但添加后import unicode_literals它不会:

# encoding: utf-8
from __future__ import unicode_literals
html = 'helló wörld'
if isinstance(html, unicode):
    html = html.encode('utf-8')
print 'DEBUG: %s' % html

输出:

Traceback (most recent call last):
  File "test.py", line 6, in 
    print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)

它失败,因为'DEBUG: %s'是一个unicode字符串,因此python尝试解码html.修复打印的几种方法是做print str('DEBUG: %s') % htmlprint 'DEBUG: %s' % html.decode('utf-8').

我希望这可以帮助您了解使用unicode字符串时的潜在问题.


我建议使用`decode()`解决方案而不是`str()`或`encode()`解决方案:使用Unicode对象的次数越多,代码就越清晰,因为你想要的是操作字符串,而不是具有外部隐含编码的字节数组.
@Kos:我认为他的意思是将"utf-8编码字符串"*对象*与unicode(因此解码)*对象*混合.前者是`str`类型,后者是类型`unicode`.作为不同的对象,如果您尝试对它们进行求和/插值,则可能会出现问题
请修复你的术语.`当你将utf-8编码的字符串与unicode字符串混合时,UTF-8和Unicode不是2种不同的编码; Unicode是标准,UTF-8是它定义的编码之一.

2> mfazekas..:

同样在2.6(在python 2.6.5 RC1 +之前),unicode文字与关键字参数不一致(issue4978):

以下代码例如在没有unicode_literals的情况下工作,但在TypeError中失败:keywords must be string如果使用unicode_literals.

  >>> def foo(a=None): pass
  ...
  >>> foo(**{'a':1})
  Traceback (most recent call last):
    File "", line 1, in 
      TypeError: foo() keywords must be strings


仅供参考,python 2.6.5 RC1 +修复此问题.

3> Jacob Gabrie..:

我确实发现,如果你添加unicode_literals指令,你还应该添加如下内容:

 # -*- coding: utf-8

你的.py文件到第一行或第二行.否则行如:

 foo = "barré"

导致如下错误:

SyntaxError: Non-ASCII character '\xc3' in file mumble.py on line 198,
 but no encoding declared; see http://www.python.org/peps/pep-0263.html 
 for details


+1.虽然你不应该在*所有情况下这样做吗?
@IanMackinnon:Python 3假定默认情况下文件是UTF8
@endolith:但是Python 2没有,如果你使用非ascii chars*甚至在评论*中它会给出语法错误!所以恕我直言`# - * - 编码:utf-8`是一个几乎是强制性的声明,无论你是否使用`unicode_literals`
Emacs兼容性[要求](https://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html)``# - * - coding:utf-8 - * - ``使用"编码"(不是"编码"或"文件编码"或其他任何东西 - Python只会查找"编码"而不管任何前缀).
无论你是否从__future__导入unicode_literals`,都会收到此错误.

4> hvr..:

还要考虑到unicode_literal会影响eval()但不影响repr()(不对称行为,即imho是一个bug),即eval(repr(b'\xa4'))不等于b'\xa4'(与Python 3一样).

理想情况下,对于unicode_literalsPython {2.7,3.x}用法的所有组合,以下代码将是一个不变的,它应该始终有效:

from __future__ import unicode_literals

bstr = b'\xa4'
assert eval(repr(bstr)) == bstr # fails in Python 2.7, holds in 3.1+

ustr = '\xa4'
assert eval(repr(ustr)) == ustr # holds in Python 2.7 and 3.1+

第二个断言恰好起作用,因为在Python 2.7中repr('\xa4')进行了评估u'\xa4'.


我觉得这里更大的问题是您正在使用`repr`来重新生成对象。[`repr`文档](https://docs.python.org/2/library/functions.html#func-repr)明确指出,这*不是*必要条件。在我看来,这将`repr`降级为仅对调试有用的东西。

5> GreenAsJade..:

还有更多.

有些库和内置函数需要不能容忍unicode的字符串.

两个例子:

内置:

myenum = type('Enum', (), enum)

(略微esotic)不适用于unicode_literals:type()需要一个字符串.

图书馆:

from wx.lib.pubsub import pub
pub.sendMessage("LOG MESSAGE", msg="no go for unicode literals")

不起作用:wx pubsub库需要一个字符串消息类型.

前者是深奥的,很容易修复

myenum = type(b'Enum', (), enum)

但是如果你的代码充满了对pub.sendMessage()(我的是)的调用,后者就是毁灭性的.

哇,嗯?!?


类型的东西也泄漏到元类中 - 所以在Django中你在`class Meta:`中声明的任何字符串都应该是`b'field_name'.
是的...在我的情况下,我意识到用b'版本搜索和替换所有sendMessage字符串是值得的.如果你想避免可怕的"解码"异常,没有什么比在你的程序中严格使用unicode,根据需要转换输入和输出(在我读到的一些论文中提到的"unicode三明治").总的来说,unicode_literals对我来说是个大赢家......
推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有