tl; dr / hızlı düzeltme
Python 2.x Unicode Zen - Uzun Sürüm
Kaynağı görmeden kök nedenini bilmek zor, bu yüzden genel olarak konuşmam gerekecek.
UnicodeDecodeError: 'ascii' codec can't decode byte
genellikle str
ASCII olmayan bir Python 2.x'i özgün dizenin kodlamasını belirtmeden bir Unicode dizesine dönüştürmeye çalıştığınızda olur .
Kısacası, Unicode dizeleri herhangi bir kodlama içermeyen tamamen ayrı bir Python dizesidir. Yalnızca Unicode nokta kodlarına sahiptirler ve bu nedenle tüm spektrumdaki herhangi bir Unicode noktasını tutabilirler. Dizeler UTF-8, UTF-16, ISO-8895-1, GBK, Big5 vb. Kodlanmış metin içerir. Dizeler Unicode olarak kodlanır ve Unicodes dizelere kodlanır . Dosyalar ve metin verileri her zaman kodlanmış dizelerde aktarılır.
Markdown modülü yazarları büyük olasılıkla unicode()
(istisnanın atıldığı yerlerde) kodun geri kalanına kaliteli bir kapı olarak kullanırlar - ASCII'yi dönüştürür veya mevcut Unicodes dizelerini yeni bir Unicode dizesine yeniden sarar. Markdown yazarları gelen dizenin kodlamasını bilemez, bu nedenle Markdown'a geçmeden önce dizeleri Unicode dizelerine deşifre etmenize güvenir.
Unicode dizeleri kodunuzda u
önek . Örneğin
>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
Unicode dizeleri dosya, veritabanları ve ağ modüllerinden de gelebilir. Bu olduğunda, kodlama hakkında endişelenmenize gerek yoktur.
Sorunlar
str
Açıkça aramasanız bile, Unicode'a dönüşüm gerçekleşebilirunicode()
.
Aşağıdaki senaryolar UnicodeDecodeError
istisnalara neden olur :
# Explicit conversion without encoding
unicode('€')
# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')
# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'
# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'
Örnekler
Aşağıdaki şemada, café
terminal tipine bağlı olarak kelimenin "UTF-8" veya "Cp1252" kodlamasında nasıl kodlandığını görebilirsiniz . Her iki örnekte caf
de sadece düzenli ascii. UTF-8'de é
iki bayt kullanılarak kodlanır. "Cp1252" de, é 0xE9'dur (bu aynı zamanda Unicode nokta değeri de olur (tesadüf değildir)). Doğru decode()
çağrılır ve bir Python Unicode'a dönüştürme başarılı olur:
Bu şemada, decode()
ile çağrılır ascii
( unicode()
verilen kodlama olmadan çağrı ile aynıdır ). ASCII'den daha büyük bayt içeremediğinden 0x7F
, bu bir UnicodeDecodeError
istisna oluşturur:
Unicode Sandviç
Kodunuzda Unicode sandviç oluşturmak, tüm gelen verileri Unicode dizelerine kodlamak, Unicodes ile çalışmak ve sonra kodlamak için iyi bir uygulamadır. str
iyi bir uygulamadır. Bu, kodunuzun ortasındaki dizelerin kodlanması konusunda endişelenmenizi önler.
Giriş / Kod Çözme
Kaynak kodu
ASCII olmayan kaynak kodunuzu pişirmek gerekiyorsa, dizeye bir önek ekleyerek Unicode dizeleri oluşturun u
. Örneğin
u'Zürich'
Python'un kaynak kodunuzun kodunu çözmesine izin vermek için, dosyanızın gerçek kodlamasına uygun bir kodlama başlığı eklemeniz gerekir. Örneğin, dosyanız 'UTF-8' olarak kodlanmışsa, şunu kullanırsınız:
# encoding: utf-8
Bu, yalnızca ASCII olmayan cihazlarınızda kaynak kodunuzda kod .
Dosyalar
Genellikle ASCII olmayan veriler bir dosyadan alınır. io
Modül, belirli kullanarak, anında dosyanızı çözen bir TextWrapper sağlar encoding
. Dosya için doğru kodlamayı kullanmalısınız - kolayca tahmin edilemez. Örneğin, UTF-8 dosyası için:
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
my_unicode_string = my_file.read()
my_unicode_string
daha sonra Markdown'a geçmek için uygun olacaktır. Satırdan bir UnicodeDecodeError
ise, read()
muhtemelen yanlış kodlama değerini kullandınız.
CSV Dosyaları
Python 2.7 CSV modülü ASCII olmayan karakterleri 😩 desteklemez. Ancak https://pypi.python.org/pypi/backports.csv ile yardım elinizin altında .
Yukarıdaki gibi kullanın, ancak açılan dosyayı ona iletin:
from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
for row in csv.reader(my_file):
yield row
Veritabanları
Çoğu Python veritabanı sürücüsü Unicode'da veri döndürebilir, ancak genellikle küçük bir yapılandırma gerektirir. SQL sorguları için her zaman Unicode dizelerini kullanın.
MySQL
Bağlantı dizesine şunu ekleyin:
charset='utf8',
use_unicode=True
Örneğin
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL
Ekle:
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
HTTP
Web sayfaları hemen hemen her kodlamayla kodlanabilir. Content-type
Başlık bir içermelidir charset
kodlama ipucu alanını. Daha sonra içerik bu değere göre manuel olarak çözülebilir. Alternatif olarak, Python-Requests , içinde Unicodes döndürür response.text
.
el ile
Dizeleri manuel olarak deşifre etmeniz gerekiyorsa , uygun kodlamanın my_string.decode(encoding)
nerede encoding
olduğunu basitçe yapabilirsiniz . Python 2.x destekli kodekler burada verilmektedir: Standart Kodlamalar . Yine, eğer alırsanız UnicodeDecodeError
muhtemelen yanlış kodlamaya sahip olursunuz.
Sandviç eti
Normal strlerde olduğu gibi Unicodes ile çalışın.
Çıktı
stdout / yazdırma
print
stdout akışı üzerinden yazar. Python, Unicodes'un konsolun kodlamasına kodlanması için stdout'ta bir kodlayıcı yapılandırmaya çalışır. Örneğin, bir Linux kabuğu locale
ise en_GB.UTF-8
, çıktı kodlanacaktır UTF-8
. Windows'da, 8 bitlik bir kod sayfasıyla sınırlı olacaksınız.
Bozuk yerel ayar gibi yanlış yapılandırılmış bir konsol beklenmeyen yazdırma hatalarına neden olabilir. PYTHONIOENCODING
ortam değişkeni stdout için kodlamayı zorlayabilir.
Dosyalar
Giriş gibi, io.open
Unicodes'i kodlanmış bayt dizelerine şeffaf olarak dönüştürmek için kullanılabilir.
Veri tabanı
Aynı okuma konfigürasyonu Unicodes'un doğrudan yazılmasına izin verecektir.
Python 3
Python 3, Python 2.x'ten daha fazla Unicode yeteneğine sahip değildir, ancak konuyla ilgili biraz daha az karışıktır. Örneğin, normal str
artık bir Unicode dizesi ve eski str
artık bytes
.
Varsayılan kodlama UTF-8'dir, bu nedenle .decode()
kodlama yapmadan bir bayt dizesi kullanırsanız, Python 3 UTF-8 kodlamasını kullanır. Bu muhtemelen insanların Unicode sorunlarının% 50'sini giderir.
Ayrıca, open()
varsayılan olarak metin modunda çalışır, bu nedenle kodu çözülmüş str
(Unicode olanlar) döndürür . Kodlama, Un * x sistemlerinde UTF-8 veya Windows kutularında windows-1251 gibi 8 bit kod sayfası olma eğiliminde olan yerel ayarınızdan türetilir.
Neden kullanmamalısın sys.setdefaultencoding('utf8')
Sadece reload
sorunları maskeleyecek ve Python 3.x'e geçişinizi engelleyecek kötü bir kesmek (kullanmanız için bir neden var ). Sorunu anlayın, temel nedeni düzeltin ve Unicode zen'in tadını çıkarın. Bkz. Neden bir py betiğinde sys.setdefaultencoding ("utf-8") kullanmamalıyız? daha fazla detay için