UnicodeDecodeError:'utf8'编解码器无法解码字节0x9c


289

我有一个套接字服务器,应该从客户端接收UTF-8有效字符。

问题是某些客户端(主要是黑客)正在通过它发送所有错误的数据。

我可以轻松地区分真正的客户端,但是我会将所有发送的数据记录到文件中,以便以后进行分析。

有时我会得到这样的œ导致UnicodeDecodeError错误的字符。

我需要使字符串UTF-8带有或不带有这些字符。


更新:

对于我的特殊情况,套接字服务是MTA,因此我只希望接收ASCII命令,例如:

EHLO example.com
MAIL FROM: <john.doe@example.com>
...

我将所有这些都记录在JSON中。

然后,一些没有好主意的人决定出售各种垃圾。

这就是为什么对于我的特定情况,完全可以剥离非ASCII字符。


1
字符串是从文件还是套接字中输出的?您能否在通过套接字/文件处理程序发送之前,发布有关如何对字符串进行最终解码的编码示例?
devsnd 2012年

我写还是不写字符串从套接字传过来?我只是简单地从套接字读取字符串,并将其放入字典中,然后使用JSON进行发送。由于这些字符,JSON函数失败。
transilvlad12年

您能将问题的样本数据放入吗
Shubham Sharma

Answers:


343

http://docs.python.org/howto/unicode.html#the-unicode-type

str = unicode(str, errors='replace')

要么

str = unicode(str, errors='ignore')

注意: 这将删除(忽略)有问题的字符,并返回不包含这些字符的字符串。

对我而言,这是理想的情况,因为我将其用作针对非ASCII输入的保护,这是我的应用程序所不允许的。

或者:使用codecs模块中的open方法读取文件:

import codecs
with codecs.open(file_name, 'r', encoding='utf-8',
                 errors='ignore') as fdata:

45
是的,尽管这通常是不好的做法/危险的做法,因为您只会丢掉角色。最好确定或检测输入字符串的编码,然后先将其解码为unicode,然后编码为UTF-8,例如:str.decode('cp1252').encode('utf-8')
Ben Hoyt 2012年

在某些情况下,您是对的,这可能会导致问题。在我的情况下,我并不在乎它们,因为它们似乎是多余的字符,这些字符来自与我的套接字服务器连接的客户端的格式和编程不正确。
transilvlad12年

如果字符串的内容实际上是无效的,那么这实际上会有所帮助,在我的情况下'\xc0msterdam',这将u'\ufffdmsterdam'替换为
PvdL 2016年

3
如果您由于在读取文件时遇到问题而在此处结束,则以二进制模式打开文件可能会有所帮助:open(file_name, "rb")然后应用上面注释中的Ben的方法
kristian 2016年

相同的选项甚至适用于更多选项,例如“ something.decode()”
亚历山大·斯托尔

83

将引擎从C更改为Python确实帮了我大忙。

引擎是C:

pd.read_csv(gdp_path, sep='\t', engine='c')

'utf-8'编解码器无法解码位置18的字节0x92:无效的起始字节

引擎是Python:

pd.read_csv(gdp_path, sep='\t', engine='python')

对我来说没有错误。


3
这实际上是一个很好的解决方案。我不知道为什么它被否决了。
ℕʘʘḆḽḘ

如果csv文件很大,这可能不是一个好主意。这可能会导致您OutOfMemory出错或笔记本计算机内核自动重启。您应该encoding在这种情况下设置。
LucasBr

1
极好的答案。谢谢。这对我有用。我在导致该问题的菱形字符中包含“?”。凭直觉我有英寸。我做了两件事要弄清楚。a)df = pd.read_csv('test.csv',n_rows = 10000)。这在没有引擎的情况下完美运行。所以我增加了n_rows来找出哪一行有错误。b)df = pd.read_csv('test.csv',engine ='python')。这行得通,我使用df.iloc [36145]打印了错误的行,这向我打印了错误的记录。
Jagannath Banerjee

1
这也对我有用。。。不确定发生在
幕后的

1
很好的解决方案!非常感谢。
Pechi

62

现在,我开始使用Python 3时,这种类型的问题就冒出来了。我不知道Python 2只是在蒸腾文件编码方面的任何问题。

在上述方法都不适合我之后,我找到了关于差异以及如何找到解决方案的很好的解释。

http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html

简而言之,要使Python 3的行为与Python 2尽可能相似,请使用:

with open(filename, encoding="latin-1") as datafile:
    # work on datafile here

但是,请阅读文章,没有一种适合所有解决方案的尺寸。


29
>>> '\x9c'.decode('cp1252')
u'\u0153'
>>> print '\x9c'.decode('cp1252')
œ

16
我很困惑,您如何选择cp1252?它对我有用,但是为什么呢?我不知道,现在我迷路了:/。你能详细说明一下吗?非常感谢 !:)
西里尔(Cyril N.)

4
您能否提出一个适用于所有角色的选项?有没有一种方法可以检测需要解码的字符,以便可以实现更通用的代码?我看到很多人都在关注这个问题,我敢打赌一些丢弃不是我想要的选项。
transilvlad13 2013年

如您所见,这个问题非常受欢迎。认为您可以使用更通用的解决方案来扩展答案?
transilvlad13年

13
没有更多通用的解决方案来“猜测编码轮盘赌”
Puppy

5
通过网络搜索,运气和直觉的组合找到了它:cp1252used by default in the legacy components of Microsoft Windows in English and some other Western languages
bolov

24

我有同样的问题,UnicodeDecodeError我用这条线解决了。不知道这是否是最好的方法,但是对我有用。

str = str.decode('unicode_escape').encode('utf-8')

13

首先,使用get_encoding_type来获取编码的文件类型:

import os    
from chardet import detect

# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']

第二,打开以下类型的文件:

open(current_file, 'r', encoding = get_encoding_type, errors='ignore')

1
当它返回None会发生什么
盖章Labalagun

3

万一有人有同样的问题。我将Vim与YouCompleteMe一起使用,无法通过此错误消息启动ycmd,我所做的是:export LC_CTYPE="en_US.UTF-8",问题消失了。


2
这与这个问题有什么关系?
transilvlad 2014年

1
如果您知道完成工作的方式,则完全相同。Ycm插件是套接字体系结构,客户端和服务器之间的通信使用套接字,两者都是python模块,如果编码设置不正确,则无法解码数据包
workplaylifecycle 2014年

我也有同样的问题。你能告诉我放export LC_CTYPE="en_US.UTF-8"哪里吗?
Reman 2014年

@Remonn嗨,您知道我们有bash的配置文件吗?放进去。
workplaylifecycle 2014年

@hylepo,我在Windows系统上:)
Reman

3

如果需要对文件进行更改但不知道文件的编码,该怎么办?如果您知道编码是ASCII兼容的,并且只想检查或修改ASCII部分,则可以使用surrogateescape错误处理程序打开文件:

with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
    data = f.read()

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.