在执行以下代码时抛出“UnicodeDecodeError:'ascii'编解码器无法解码位置2中的字节0xc2:序号不在范围内(128)”:
filename = 'Spywaj.ttf'
print repr(filename)
>> 'Sp\xc2\x88ywaj.ttf'
filepath = os.path.join('/dirname', filename)
但该文件有效且存在于磁盘上。文件名是从“unzip -l”命令中提取的。如何加入像这样的文件名?
操作系统和文件系统
Filesystem: ext3 relatime,errors=remount-ro 0 0
Locale: en_US.UTF-8
Alex的建议 os.path.join现在正常工作,但我仍然无法使用它加入的文件名访问磁盘上的文件。
filename = filename.decode('utf-8')
filepath = os.path.join('/dirname', filename)
print filepath
>> /dirname/u'Sp\xc2\x88ywaj.ttf'
print os.path.isfile(filepath)
>> False
new_filepath = filepath.encode('Latin-1').encode('utf-8')
print new_filepath
>> /dirname/u'Sp\xc2\x88ywaj.ttf'
print type(filepath)
>> <type 'unicode'>
print os.path.isfile(new_filepath)
>> False
valid_filepath = glob.glob('/dirname/*.ttf')[0]
print valid_filepath
>> /dirname/Spywaj.ttf (SO cannot display the chars in filename)
print type(valid_filepath)
>> <type 'str'>
print os.path.isfile(valid_filepath)
>> True
答案 0 :(得分:8)
在Latin-1(ISO-8859-1)和Windows-1252中,0xc2将是具有回音重音的大写字母A ...似乎不会出现在您显示的代码中的任何位置!你能加一个
吗?print repr(filename)
在os.path.join
调用之前(并且还将'/dirname'
放入变量并打印其repr以获得完整性?)。我想也许那个流浪的角色 那里,但是由于某些原因你没有看到它 - repr
会揭示它。
如果你的文件名中有一个Latin-1(或Win-1252)非Ascii字符,你必须使用Unicode - 和/或根据你的操作系统和文件系统,使用一些特定的编码。
编辑:由于repr
,OP确认实际上两个字节不可能是ASCII - 0xc2然后是0x88,对应于OP认为是一个小写L.
好吧,那个序列将是一个带有插入符号(代码点0x88)的Unicode大写字母A,在刚刚流行的 UTF-8 编码中 - 对于OP乞丐的解释,它看起来像小写字母L,但我想<一些字体可能在图形上疯狂,足以造成这种混乱。
所以我首先尝试filename = filename.decode('utf-8')
- 这应该允许os.path.join
工作。如果open
然后对生成的Unicode字符串进行调整(它可能有效,具体取决于文件系统和操作系统),则下一次尝试是尝试使用该Unicode对象的.encode('Latin-1')
和.encode('utf-8')
。如果所有编码都不起作用,那么我认为OP尚未提供的操作系统和文件系统的信息变得至关重要。
答案 1 :(得分:6)
我通过将这些行添加到/etc/apache2/envvars
并重新启动Apache来修复了UnicodeDecodeError。
export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'
如下所述: https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/modwsgi/#if-you-get-a-unicodeencodeerror
我花了一些时间来调试它。
答案 2 :(得分:2)
filename = filename.decode('utf-8').encode("latin-1")
适用于我Splywaj.zip
的文件>>> os.path.isfile(filename.decode("utf8").encode("latin-1"))
True
>>>
答案 3 :(得分:0)
在执行以下代码时抛出“UnicodeDecodeError:'ascii'编解码器无法解码位置2中的字节0xc2:序号不在范围内(128)”:
filename = 'Spywaj.ttf'
print repr(filename)
>> 'Sp\xc2\x88ywaj.ttf'
filepath = os.path.join('/dirname', filename)
我无法看到如何获得该异常 - os.path.join的两个args都是str对象。没有理由尝试将任何东西转换为unicode。您确定上面的代码与您的运行完全一致吗?
Alex的建议os.path.join现在可以正常工作,但我仍然无法使用它加入的文件名访问磁盘上的文件。
filename = filename.decode('utf-8')
filepath = os.path.join('/dirname', filename)
print filepath
>> /dirname/u'Sp\xc2\x88ywaj.ttf'
抱歉,假设filename
没有从上一个代码段改变,那肯定是不可能的。它看起来像os.path.join('/dirname', repr(filename))
的结果......请确保您发布实际运行的代码以及实际输出(以及实际的回溯,如果有的话)。
new_filepath = filepath.encode('Latin-1').encode('utf-8')
亚历克斯意味着尝试两次,每次都使用其中一种编码 - 两次编码都不要尝试一次!由于filepath中的所有字符都在ASCII范围内(参见证据问题2),效果只是filepath.encode('ascii')
您知道如何找到您感兴趣的文件的名称:
valid_filepath = glob.glob('/dirname/*.ttf')[0]
如果您必须在脚本中对该名称进行硬编码,则可以使用repr()函数来获取可以在脚本中键入的表示形式,而无需担心utf8,unicode,编码,解码和所有噪声:< / p>
print repr(valid_filepath)
我们假设它打印'/dirname/Sp\xc2\x88ywaj.ttf'
...然后您需要做的就是仔细复制并将其粘贴到您的脚本中:
file_path = '/dirname/Sp\xc2\x88ywaj.ttf'