119

我正在尝试使用一个非常大的数据集,其中包含一些非标准字符。根据工作规范,我需要使用 unicode,但我很困惑。(而且很可能做错了。)

我使用以下方法打开 CSV:

 15     ncesReader = csv.reader(open('geocoded_output.csv', 'rb'), delimiter='\t', quotechar='"')

然后,我尝试使用以下代码对其进行编码:

name=school_name.encode('utf-8'), street=row[9].encode('utf-8'), city=row[10].encode('utf-8'), state=row[11].encode('utf-8'), zip5=row[12], zip4=row[13],county=row[25].encode('utf-8'), lat=row[22], lng=row[23])

我正在对除 lat 和 lng 之外的所有内容进行编码,因为它们需要发送到 API。当我运行程序将数据集解析为我可以使用的内容时,我得到以下 Traceback。

Traceback (most recent call last):
  File "push_into_db.py", line 80, in <module>
    main()
  File "push_into_db.py", line 74, in main
    district_map = buildDistrictSchoolMap()
  File "push_into_db.py", line 32, in buildDistrictSchoolMap
    county=row[25].encode('utf-8'), lat=row[22], lng=row[23])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

我想我应该告诉你我正在使用 python 2.7.2,这是基于 django 1.4 构建的应用程序的一部分。我已经阅读了有关此主题的几篇文章,但似乎没有一篇直接适用。任何帮助将不胜感激。

您可能还想知道导致问题的一些非标准字符是 Ñ 并且可能是 É。

4

11 回答 11

160

Unicode 不等于 UTF-8。后者只是前者的编码

你做错了。您正在读取UTF-8编码的数据,因此您必须将 UTF-8 编码的字符串解码为 un​​icode 字符串。

所以只需替换.encode.decode,它应该可以工作(如果你的 .csv 是 UTF-8 编码的)。

不过也没什么好丢脸的。我敢打赌,五分之三的程序员一开始都很难理解这一点,如果不是更多的话;)

更新:如果您的输入数据不是UTF-8 编码的,那么您当然必须.decode()使用适当的编码。如果没有给出任何内容,python 假定 ASCII,这显然在非 ASCII 字符上失败。

于 2012-05-02T00:21:01.067 回答
92

只需将此行添加到您的代码中:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')
于 2016-10-31T17:00:11.207 回答
39

对于 Python 3 用户。你可以做

with open(csv_name_here, 'r', encoding="utf-8") as f:
    #some codes

它也适用于烧瓶:)

于 2017-10-20T14:29:26.610 回答
10

错误的主要原因是python假设的默认编码是ASCII。因此,如果要编码的字符串数据encode('utf8')包含超出 ASCII 范围的字符,例如对于像“hgvcj터파크387”这样的字符串,python 会抛出错误,因为该字符串不是预期的编码格式。

如果您使用的 python 版本早于 3.5 版,可靠的解决方法是将 python 假定的默认编码设置为utf8

import sys
reload(sys)
sys.setdefaultencoding('utf8')
name = school_name.encode('utf8')

这样,python 将能够预测字符串中超出 ASCII 范围的字符。

但是,如果您使用的是 python 3.5 或更高版本,则 reload() 函数不可用,因此您必须使用 decode 来修复它,例如

name = school_name.decode('utf8').encode('utf8')
于 2017-07-11T14:35:17.430 回答
3

对于 Python 3 用户:

将编码从“ascii”更改为“latin1”有效。

此外,您可以尝试通过使用以下代码段读取前 10000 个字节来自动查找编码:

import chardet  
with open("dataset_path", 'rb') as rawdata:  
            result = chardet.detect(rawdata.read(10000))  
print(result)
于 2018-03-29T23:58:35.407 回答
3

我的电脑设置了错误的语言环境。

我第一次做

>>> import locale
>>> locale.getpreferredencoding(False)
'ANSI_X3.4-1968'

locale.getpreferredencoding(False)open()是您不提供编码时调用的函数。输出应该是'UTF-8',但在这种情况下,它是 ASCII 的一些变体

然后我运行了 bash 命令locale并得到了这个输出

$ locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

因此,我使用了默认的 Ubuntu 语言环境,这会导致 Python 以 ASCII 而不是 UTF-8 格式打开文件。我必须将我的语言环境设置en_US.UTF-8

sudo apt install locales 
sudo locale-gen en_US en_US.UTF-8    
sudo dpkg-reconfigure locales

如果您无法在系统范围内更改语言环境,则可以像这样调用所有 Python 代码:

PYTHONIOENCODING="UTF-8" python3 ./path/to/your/script.py

或者做

export PYTHONIOENCODING="UTF-8"

将其设置在您运行它的外壳中。

于 2019-12-11T19:39:05.207 回答
1

如果您在创建或更新证书时运行 certbot 时遇到此问题,请使用以下方法

grep -r -P '[^\x00-\x7f]' /etc/apache2 /etc/letsencrypt /etc/nginx

该命令在评论的一个 .conf 文件中发现了有问题的字符“´”。删除它(您可以根据需要编辑评论)并重新加载 nginx 后,一切都恢复了。

来源:https ://github.com/certbot/certbot/issues/5236

于 2019-07-12T08:21:58.757 回答
0

由于纬度和经度,使用编码 UTF 16 打开。

with open(csv_name_here, 'r', encoding="utf-16") as f:
于 2019-06-17T20:13:12.640 回答
0

或者当您在 Python 中处理文本时,如果它是 Unicode 文本,请记下它是 Unicode。

设置text=u'unicode text'而不是text='unicode text'.

这在我的情况下有效。

于 2020-01-02T22:33:44.580 回答
0

它只通过使用参数'rb'读取二进制而不是'r'读取来工作

于 2020-06-23T11:05:12.523 回答
0

在 Docker 容器中处理这个问题。可能是这种情况(对我而言),您只需要生成语言环境而无需执行任何其他操作:

sudo locale-gen en_US en_US.UTF-8

在某些情况下,这对我来说已经足够了,因为已经安装和配置了语言环境。如果您必须安装语言环境并对其进行配置,请将以下部分添加到您的 Dockerfile 中:

RUN apt update && apt install locales && \
    sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=en_US.UTF-8

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8
ENV LC_ALL en_US.UTF-8

我是这样测试的:

cat <<EOF > /tmp/test.txt
++*=|@#|¼üöäàéàè!´]]¬|¢|¢¬|{ł|¼½{}}
EOF

python3
import pathlib; pathlib.Path("/tmp/test.txt").read_text()
于 2021-09-15T13:03:44.653 回答