簡體   English   中英

UnicodeDecodeError:“ascii”編解碼器無法解碼位置 2 中的字節 0xd1:序數不在范圍內(128)

[英]UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128)

我正在嘗試使用一個非常大的數據集,其中包含一些非標准字符。 根據工作規范,我需要使用 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 構建的應用程序的一部分。 我已經閱讀了有關此主題的幾篇文章,但似乎沒有一篇直接適用。 任何幫助將不勝感激。

您可能還想知道導致問題的一些非標准字符是 Ñ 並且可能是 É。

Unicode 不等於 UTF-8。 后者只是前者的編碼

你做錯了。 您正在讀取UTF-8編碼的數據,因此您必須將 UTF-8 編碼的字符串解碼為 un​​icode 字符串。

所以只需用.encode替換.decode ,它應該可以工作(如果你的 .csv 是 UTF-8 編碼的)。

不過也沒什么好丟臉的。 我敢打賭,五分之三的程序員一開始都很難理解這一點,如果不是更多的話;)

更新:如果您的輸入數據不是UTF-8 編碼的,那么您當然必須使用適當的編碼進行.decode() 如果沒有給出任何內容,python 假定 ASCII,這顯然在非 ASCII 字符上失敗。

只需將此行添加到您的代碼中:

1.Python2

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

2.Python3

import sys
from importlib import reload
reload(sys)
sys.setdefaultencoding('utf-8')

對於 Python 3 用戶。 你可以做

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

它也適用於燒瓶:)

錯誤的主要原因是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')

對於 Python 3 用戶:

將編碼從“ascii”更改為“latin1”有效。

此外,您可以嘗試通過使用以下代碼段讀取前 10000 個字節來自動查找編碼:

import chardet  
with open("dataset_path", 'rb') as rawdata:  
            result = chardet.detect(rawdata.read(10000))  
print(result)

我的電腦設置了錯誤的語言環境。

我第一次做

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

locale.getpreferredencoding(False)open()在您不提供 encoding 時調用的函數。 輸出應該是'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"

將其設置在您運行它的外殼中。

如果您在創建或更新證書時運行 certbot 時遇到此問題,請使用以下方法

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

該命令在評論的一個 .conf 文件中發現了有問題的字符“´”。 刪除它(您可以根據需要編輯評論)並重新加載 nginx 后,一切都恢復了。

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

由於緯度和經度,使用編碼 UTF 16 打開。

with open(csv_name_here, 'r', encoding="utf-16") as f:

或者當您在 Python 中處理文本時,如果它是 Unicode 文本,請記下它是 Unicode。

設置text=u'unicode text'而不是text='unicode text'

這在我的情況下有效。

它只通過使用參數'rb'讀取二進制而不是'r'讀取來工作

在 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()

我在使用 Pickle 卸載時遇到了這個問題。 嘗試,

data = pickle.load(f,encoding='latin1')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM