SORU
28 Aralık 2010, Salı


Dosyaya yönlendirme UnicodeDecodeError

Bu parçacık iki kez, ./test.py >out.txt ./test.py ile bir kez ve daha sonra Ubuntu terminal (kodlama utf-8 olarak ayarlayın), çalıştırın:

uni = u"\u001A\u0BC3\u1451\U0001D10C"
print uni

Yönlendirme Olmadan çöp yazdırır. Yönlendirme ile bir UnicodeDecodeError. Birisi sadece ikinci durumda hata alıyorum neden açıklamak ya da daha iyisi her iki durumda da perde arkasında neler olduğunu detaylı bir açıklaması olan var mı?

CEVAP
28 Aralık 2010, Salı


Bu tür kodlama sorunları için tüm anahtar olduğunu anlamakiki ayrı kavram"". dize : (1) stringkarakterlerve (2) dize/dizibayt. Bu ayrım olmuştur çoğunlukla göz ardı uzun zamandır çünkü tarihi aynı anda her yerde kodlamaları ile en fazla 256 karakter (ASCII, Latin-1, Windows-1252, Mac OS Roman,...): bu kodlamalar göster bir dizi ortak karakterler için sayılar arasında 0 ile 255 (bayt); nispeten sınırlı exchange dosyaları arasında zuhur web yapılan durum tolere edilebilir, en programlar olabilir görmezden gerçeği vardı birden çok kodlama sürece ürettiler metin o kaldı aynı işletim sistemi: böyle bir program ki sadece tedavi metin olarak bayt (kodlama tarafından kullanılan işletim sistemi). Doğru, modern görünümü düzgün bu iki dize kavramlar, aşağıdaki iki puan dayanarak ayırır:

  1. Karakterlerçoğunluklabilgisayar ile ilgisi yoktur: tebeşir bir tahta, vb., bunları çizmek edebilirsiniz gibi örnek بايثون ve 中蟒 için. "Karakterler makineleri de vardır" "çizim talimatları" gibi örneğin boşluk, yeni satır, satır başı, yazma yönü (Arapça, vb.) ayarlamak için talimatları, aksan, vb. very large character list Unicode standart dahil, bilinen karakterlerin en kapsar.

  2. Diğer taraftan, bilgisayarlar bir şekilde soyut karakteri temsil etmesi gerekiyor: bunun için kullanıyorlarbayt dizileri(0 ile 255 arasındaki sayılar dahil). Bayt karakterler dönüştürür gerekli işlemi denirkodlama. Böylece, bir bilgisayargerektirirkarakteri göstermek için bir kodlama. Herhangi bir metin bilgisayarınızda mevcut bir terminal gönderilmesini ister kodlanmış görüntülenir kadar), karakter belirli bir şekilde kodlanmış bekliyor, ya da bir dosya. Görüntülenmesi için veya düzgün "" (demek, Python yorumlayıcısı), bayt akışı . anlaşıldı ^em>çözülürkarakterlerin içine. A few encodings (UTF-8, UTF-16,...) tarafından tanımlanan Unicode listesinden karakter (Unicode böylece tanımlar hem bir listesi ve karakter kodlamaları için bu karakterler var hala yerlerde görür "ifadesi Unicode kodlaması", ama bu yanlış terminoloji, Unicode sağlar bir tercih kodlamaları).

Özetbilgisayar dahili bayt karakterleri temsil etmek gerekve onlar iki işlem sayesinde:

Kodlama: karakter bayt seçeneklerini belirleyin

Kod çözme: bayt öğelerini karakter

Bazı kodlamaları (bazı) Unicode kodlama, tüm Unicode karakterleri kodlamak için izin verirken, tüm karakterler (örneğin, ASCII) kodlamak, olamaz.

Python 2karakter dizeleri olarak adlandırılan "Unicode dizeleri" (unicode) ise byte dizileri "dizeleri" (str yazın nerede bayt dizisi için örnek olmalı inşa ile dize hazır "…").Python 3karakter dizeleri sadece denir "dizeleri bayt dizileri ise" (str türü), "" (bytes yazın). bayt Python 3 terminoloji belki daha açık ve daha genel buluyorum. (Aslında, karakter dizeleri Unicode aşan bir kavram vardır, onları Python 2 dizeleri Unicode arama kavramsal anlamını daha uygulama ayrıntı daha fazla ilgilidir. Bu isim geliyor aslında bu "yasak" Unicode karakterleri, ama onların istenilen rolü olduğunu içerdikleri karakterler, Unicode karakterleri Unicode oluyor içeren büyük tablonun karakter yaratılmış, öyle verir uygun bir liste dize karakterleri.)

Bu birkaç kilit noktaları, en ilgili sorular kodlama anlamak gerekir!

PS: Karakterlerin Unicode listesinde karakterler de varunique number(Code Point denir) ile ilişkili. Bu sayı bir Python \u \U Unicode dize sözdizimi kullanılır. Bir karakter kodlama (ve bazı Unicode karakterleri Unicode kodlama ile örneğin herhangi bir ilişki ayı, yok) ile karıştırılmamalıdır.


Normalde, ne zamanbaskıu"…"bir terminalçöp almalısınız: Python terminal. kodlamayı biliyor Aslında, terminal beklediğini kontrol edebilirsiniz:

% python
Python 2.7.6 (default, Nov 15 2013, 15:20:37) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.stdout.encoding
UTF-8

Eğer giriş terminal karakter kodlaması ile kodlanmış olabilir varsa, Python bu kadar yapacak ve şikayet etmeden kilometreye karşılık gelen bayt gönderir. Terminal sonra onun en iyi giriş baytı (en kötü ihtimalle terminal yazı tipi bazı karakterler yok ve yazdırma, boş bir tür yerine) kod çözme sonra karakterleri görüntülemek için yapar.

Giriş karakterleri veya terminal kodlama ile kodlanmış, daha sonra terminal bu karakterleri göstermek için yapılandırılmamış demektir. Python şikayet edecek (karakteri beri UnicodeEncodeError terminalinizin uygun bir şekilde kodlanmış edilemez bir dize ile Python). Mümkün olan tek çözüm kullanmaktır bir terminal olabilir ekran karakterleri (ya da yapılandırma terminal böylece kabul ettiği bir kodlama olabilir temsil karakter, ya da kullanarak farklı bir terminal programı). Bu farklı ortamlarda kullanılabilecek programlar dağıtırken önemlidir: yazdırma bu mesajlar kullanıcının terminal gösterilebilir olmalıdır. Bazen bu nedenle yalnızca ASCII karakterler içeren dizeler için sopa.

Ancak, ne zamanyönlendirme veya boru çıktıprograma, o zaman genellikle mümkün bilmek girdi kodlama alma programı ve yukarıdaki kod verir bazı varsayılan kodlama: Yok (Python 2.7) veya UTF-8 (Python 3):

% python2.7 -c "import sys; print sys.stdout.encoding" | cat
None
% python3.4 -c "import sys; print(sys.stdout.encoding)" | cat
UTF-8

Stdin, stdout ve stderr kodlama ancak gerekirse set PYTHONIOENCODING çevre ile değişken olabilir:

% PYTHONIOENCODING=UTF-8 python2.7 -c "import sys; print sys.stdout.encoding" | cat
UTF-8

Eğer baskı için bir terminal üretmek değil, ne bekliyorsun, kontrol edebilirsiniz UTF-8 kodlaması bu koymak elle doğrudur; örneğin, ilk karakter (\u001A) yazdırılabilir, if I'm not mistaken.

Daha fazla bilgi için: http://wiki.python.org/moin/PrintFails. Bu linkten bu gibi bir çözüm, Python 2 için bulabilirsiniz.x:

import codecs
import locale
import sys

# Wrap sys.stdout into a StreamWriter to allow writing unicode.
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout) 

uni = u"\u001A\u0BC3\u1451\U0001D10C"
print uni

Python için 3, StackOverflow üzerinde one of the questions asked previously kontrol edebilirsiniz.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ASUS

    ASUS

    22 EKİM 2005
  • KliptOut KwazeeKilla

    KliptOut Kwa

    24 ŞUBAT 2010
  • LiquidMusick

    LiquidMusick

    23 Aralık 2010