(unicode错误)'unicodeescape'编解码器无法解码字节 - 含有'\u'的字符串
我在写Python 2.6的代码,但考虑到将来可能会用到Python 3,所以我觉得在一些模块的顶部加上
from __future__ import unicode_literals
是个好主意。换句话说,我是在主动制造一些麻烦(为了将来避免这些麻烦),但我可能缺少一些重要的知识。我希望能够传递一个表示文件路径的字符串,并像这样简单地创建一个对象:
MyObject('H:\unittests')
在Python 2.6中,这样做没问题,不需要使用双反斜杠或者原始字符串,即使是以'\u..'
开头的目录,这正是我想要的。在__init__
方法中,我确保所有单个的\
都被解释为'\\
',包括那些在特殊字符前面的,比如\a
、\b
、\f
、\n
、\r
、\t
和\v
(只有\x
仍然是个问题)。此外,使用(本地)编码将给定字符串解码为unicode也能按预期工作。
为了准备Python 3.x,我在编辑器中模拟我的实际问题(从一个干净的Python 2.6控制台开始),发生了以下情况:
>>> '\u'
'\\u'
>>> r'\u'
'\\u'
(到这里都正常:'\u'
被控制台用本地编码编码)
>>> from __future__ import unicode_literals
>>> '\u'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: end of string in escape sequence
换句话说,这个(unicode)字符串根本没有被解释为unicode,也没有自动用本地编码解码。即使是原始字符串也是如此:
>>> r'\u'
SyntaxError: (unicode error) 'rawunicodeescape' codec can't decode bytes in position 0-1: truncated \uXXXX
对于u'\u'
也是一样:
>>> u'\u'
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: end of string in escape sequence
此外,我本来期待isinstance(str(''), unicode)
返回True
(但实际上并没有),因为导入unicode_literals应该让所有字符串类型都变成unicode。(编辑:)因为在Python 3中,所有字符串都是Unicode字符的序列,我本来期待str('')
返回这样的unicode字符串,type(str(''))
应该同时是<type 'unicode'>
和<type 'str'>
(因为所有字符串都是unicode),但我也意识到<type 'unicode'>并不是<type 'str'>
。真是让人困惑……
问题
- 我该如何最好地传递包含'
\u
'的字符串?(不想写'\\u
') from __future__ import unicode_literals
真的实现了所有与Python 3相关的unicode变化吗,这样我就能得到一个完整的Python 3字符串环境?
编辑:
在Python 3中,<type 'str'>
是一个Unicode对象,而<type 'unicode'>
根本不存在。在我的情况下,我想为Python 2(.6)写代码,使其在Python 3中也能工作。但是当我import unicode_literals
时,我无法检查一个字符串是否是<type 'unicode'>
,因为:
- 我认为
unicode
不在命名空间中 - 如果
unicode
在命名空间中,<type 'str'>
的字面量在同一个模块中创建时仍然是unicode type(mystring)
在Python 3中对于unicode字面量总是返回<type 'str'>
我的模块通常通过在顶部加上# coding: UTF-8
注释来编码为'utf-8',而我的locale.getdefaultlocale()[1]
返回'cp1252'。所以如果我从控制台调用MyObject('çça')
,在Python 2中它会被编码为'cp1252',而从模块调用MyObject('çça')
时则是'utf-8'。在Python 3中,它不会被编码,而是一个unicode字面量。
编辑:
我已经放弃了希望,认为可以避免在u
(或者x
)前面使用'\'。我也理解导入unicode_literals
的限制。然而,从模块到控制台以及反向传递字符串的许多可能组合,以及每种不同编码的情况,再加上导入unicode_literals
与否和Python 2与Python 3之间的差异,让我想通过实际测试来创建一个概述。因此下面有一个表格。
换句话说,type(str(''))
在Python 3中不会返回<type 'str'>
,而是<class 'str'>
,所有Python 2的问题似乎都被避免了。
4 个回答
我在Python 3上试了这个:
import os
os.path.abspath("yourPath")
结果成功了!
对我来说,这个问题跟版本不更新有关,这里指的是 numpy
这个库。
要解决这个问题:
conda install -f numpy
据我所知,from __future__ import unicode_literals
这个语句的作用就是让所有的字符串字面量都变成unicode类型,而不是普通字符串类型。也就是说:
>>> type('')
<type 'str'>
>>> from __future__ import unicode_literals
>>> type('')
<type 'unicode'>
不过,str
和unicode
仍然是不同的类型,它们的表现和以前一样。
>>> type(str(''))
<type 'str'>
总是属于str
类型。
关于你提到的r'\u'
问题,这是设计使然,因为在没有unicode_literals
的情况下,它等同于ru'\u'。根据文档:
当'r'或'R'前缀与'u'或'U'前缀一起使用时,\uXXXX和\UXXXXXXXX转义序列会被处理,而所有其他的反斜杠则会保留在字符串中。
这可能是因为python2系列的词法分析器的工作方式。在python3中,它的表现会像你(和我)预期的那样。
你可以输入两个反斜杠,这样\u
就不会被解释,但你会得到两个反斜杠!
反斜杠可以用前面的反斜杠进行转义;不过,这两个反斜杠都会保留在字符串中。
>>> ur'\\u'
u'\\\\u'
所以在我看来,你有两个简单的选择:
不使用原始字符串,并转义你的反斜杠(与python3兼容):
'H:\\unittests'
聪明一点,利用unicode代码点(不与python3兼容):
r'H:\u005cunittests'