SORU
8 NİSAN 2010, PERŞEMBE


Neden varsayılan kodlama ASCII olduğunda Python print unicode karakterleri mu?

Python 2.6 kabuk: den

>>> import sys
>>> print sys.getdefaultencoding()
ascii
>>> print u'\xe9'
é
>>> 

"Karakterin ASCII bir parçası değil ve bir kodlama belirtilen görmedim." é beri de bazı anlamsız ya da bir Hata olması için baskı ifadenin bekliyordum, ASCII varsayılan kodlama olmanın anlamı ne anlamıyorum sanırım.

EDİT

I moved the edit to the Answers section and accepted it as suggested.

CEVAP
23 ŞUBAT 2014, Pazar


Çeşitli cevaplar gelen bit ve parçaları sayesinde, bir açıklama dikiş edebiliriz sanırım.

Bir unicode dize yazdırmak için çalışıyorum,'\xe9', örtülü olarak dize kodlama düzeni kullanarak şu anda sys içinde saklı.bunu kodlamak için deneyin Python u stdout.kodlama. Python aslında başlatılan bu ortamdan bu ayarı seçer. Eğer çevreye uygun bir kodlama bulabilirse, ancak o zaman mı onun için dönervarsayılanASCII.

Örneğin, bash bir kabuk varsayılan UTF-8 kodlaması kullanıyorum. Eğer Python başlarsam seçer ve bu ayarı kullanın:

$ python

>>> import sys
>>> print sys.stdout.encoding
UTF-8

Bir an için Python kabuk çıkmak ve sahte kodlama: bash ortamı hazırlayalım

$ export LC_CTYPE=klingon
# we should get some error message here, just ignore it.

Sonra yine python kabuk başlatmak ve gerçekten de varsayılan ascıı kodlaması dönmek yok emin olun.

$ python

>>> import sys
>>> print sys.stdout.encoding
ANSI_X3.4-1968

Bingo!

Eğer şimdi ascıı dışında bazı unicode karakter çıkış için çalışırsanız güzel bir hata iletisi almalısınız

>>> print u'\xe9'
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' 
in position 0: ordinal not in range(128)

Çıkış ve bash kabuk, Python atmak sağlar.

Şimdi çıkışları dizeleri Python sonra ne olacağını gözlemleyelim. Bu biz ilk başlangıç bash kabuk içinde bir grafik terminal (Gnome Terminal) ve set terminal için kod çözme çıkışı ile ISO-8859-1 latin-1 olarak bilinen (grafik terminaller genellikle bir seçenekKarakter Kodlamasını Ayarlamakaçılan menüleri). Bu gerçek değişmez unutmayınshell çevrekodlama, ancak böyle değişirterminalbiraz bir web tarayıcısı gibi verilen, çıkış deşifre edecektir. Bu nedenle terminal kodlama, bağımsız kabuk ortamı değiştirebilirsiniz. Hadi o zaman kabuğundan Python başlangıç ve sys olun.stdout.kodlama shell çevre kodlama için (benim için UTF-8) olarak ayarlanır:

$ python

>>> import sys

>>> print sys.stdout.encoding
UTF-8

>>> print '\xe9' # (1)
é
>>> print u'\xe9' # (2)
é
>>> print u'\xe9'.encode('latin-1') # (3)
é
>>>

(1) python, terminal aldığı gibi ikili dize Çıktıları ve latin-1 karakter haritası ile değeri eşleştirmeye çalışır. Latin-1, 0xe9 veya 233 karakter" ve böylece terminal görüntüler. "é verir

(2) python için çalışırörtülü olarakşu anda sys ayarlanır ne olursa olsun, Unicode dize kodlamak.stdout., bu durumda kodlama "UTF-8". UTF-8 kodlaması, elde edilen ikili dize sonra '\xc3\xa9 (daha sonra bakınız açıklama)'. Terminal gibi akışı alır ve 0xc3a9 latin-1, latin-1 kullanarak 255 0 gider ve bu yüzden, sadece çözer akarsu 1 byte bir anda çözmeye çalışır. 2 bayt uzunluğunda, bu nedenle 0xc3 yorumlar çözücü latin-1 (195) ve 0xa9 (169) ve 2 karakter veren 0xc3a9: - ve ©.

(3) python kodlar unicode kod noktası'\xe9' (233) latin-1 düzeni ile. u Meğer latin-1 kod puan aralığı 0 ile 255 arasında olduğunu ve bu zaman aralığında Unicode olarak aynı karakteri gösteriyor. Bu nedenle, bu dizi Unicode kod noktaları latin-1 olarak kodlanmış zaman aynı değeri verecektir. U'\xe9' (233) latin-1 olarak kodlanmış da ikili dize verir '\xe9'. Terminal değer alır ve latin-1 karakter haritada eşleştirmeye çalışır. Durum (1) gibi, "" görüntülenir. é verir

Hadi şimdi açılır menü web tarayıcınızın kodlama ayarlarını değiştirmek istiyorum () UTF-8 terminal kodlama ayarlarını değiştirmek. Hayır Python durdurmak ya da kabuk yeniden başlatmak gerekiyor. Terminal kodlama şimdi Python ile eşleşiyor. Hadi tekrar yazdırmayı deneyin:

>>> print '\xe9' # (4)

>>> print u'\xe9' # (5)
é
>>> print u'\xe9'.encode('latin-1') # (6)

>>>

(4) python çıktılarikilidize kadar. Terminal UTF-8 ile bu yayını çözmeye çalışır. Ama UTF-8 değeri 0xe9 (daha sonra bakınız açıklama) anlamıyor ve dolayısıyla unicode kod noktası için dönüştürülemiyor. Hayır kod noktası bulmuş, hiçbir karakter yazdırılır.

(5) girişimleri pythonörtülü olarakUnicode dize sys içinde kodlamak.stdout.kodlama. "UTF-8". hala Elde edilen ikili dize '\xc3\xa9'. Terminal akışı alır ve 0xc3a9 da UTF-8 kullanarak çözmeye çalışır. Unicode karakter Haritadaki sembole gösteren kod değeri 0xe9 (233), verir"". é "". É Terminal görüntüler

(6) python ile aynı değeri ikili bir dize verir, latin-1, unicode dize kodlar '\xe9'. Yine terminal için bu durum hemen hemen aynıdır (4).

Sonuç: - Python çıkışları unicode olmayan ham veri olarak dizeleri, varsayılan kodlama düşünmeden. Terminal sadece eğer geçerli bir kodlama verinin görüntülemek için olur. - Python çıkışları onları düzeni sys belirtilen kullanarak kodlama sonra dizeleri Unicode.stdout.kodlama. - Python shell ortamından ayarı alır. - terminal kendi kodlama ayarlarına göre çıkış görüntüler. - terminal kodlama shell den bağımsız.


Unicode hakkında daha fazla bilgi, UTF-8 ve latin-1:

Unicode temelde bazı tuşlar (kod noktaları) geleneksel olarak bazı sembolleri işaret atanmış nerede karakter tablosu. örneğin anahtar 0xe9 (233) değerini, sembol işaret ettiğini karar verildi''. é ASCII ve Unicode 255 0-latin-1 ve Unicode gibi 127, 0 ile aynı kod noktaları kullanın. Yani, 0x41 puan için 'A' ASCII, latin-1 ve Unicode, 0xc8 puan 'Ü' latin-1 ve Unicode, 0xe9 puan için 'é' latin-1 ve Unicode.

Elektronik cihazlar ile çalışırken, Unicode kod noktaları verimli bir şekilde elektronik olarak temsil edilmesi gerekiyor. Bu kodlama düzeni vardır. Çeşitli programları var Unicode kodlama (utf7, UTF-8, UTF-16, UTF-32). En sezgisel ve yalındır kodlama yaklaşım olurdu sadece kullanmak için bir kod noktası değeri Unicode haritası olarak onun değer verdiği elektronik, ama Unicode şu anda bir milyondan fazla kod noktaları, bazıları iste 3 bayt olacağını ifade etti. İş etkili bir şekilde metin, bir 1: 1 eşleme olurdu oldukça kullanışsız yana olurdu gerektiren tüm kod puan depolanmak tam olarak aynı miktarda alanı, en az 3 bayt başına karakter, ne olursa olsun onların gerçek ihtiyaç.

Kodlaması unicode kod noktaları, örneğin ascıı sadece ilk latin-1 128 iken, tüm kapakları kapağı yok alanı gereksinimi ile ilgili eksiklikler var en ilk 256 kapsar. Daha kapsamlı olmaya çalışın Diğerleri "" karakterler. daha sık, hatta gereğinden fazla bayt gerektirir, çünkü aynı zamanda savurgan olmuyor,, UTF-16 için örnek, kullanan en az 2 bayt / karakter, dahil olanlar ascıı aralığı ('B' olan 65, hala gerektirir 2 bayt depolama UTF-16). UTF-32 4 bayt her karakter depolar olarak daha da savurgan.

UTF-8 zekice ikilem çözülmüş olması, bir düzeni byte boşluk değişken miktarı ile kod noktaları saklamak mümkün olur. Kodlama stratejisinin bir parçası olarak, UTF-8 (muhtemelen kod çözücüleri için) yer gereksinimlerini ve sınırlarını gösteren bir bayrak biti ile kod noktaları dantel.

UTF-8 ascıı aralığında unicode kod noktaları (0-127): kodlama

0xxx xxxx  (in binary)
  • x gerçek bir uzay "kodlama sırasında" kod noktası depolamak için ayrılmış gösteri
  • Baştaki 0 bu kod yalnızca 1 bayt gerektirir UTF-8 kod çözücü gösteren bir bayrak.
  • kodlama üzerine, UTF-8, belirli bir aralıktaki kod noktası değeri (yani 65 de 65. UTF-8 kodlanmış) değiştirmez. Unicode ve ASCII de aynı aralıkta uyumlu olduğunu düşünürsek, bu arada UTF-8 ve ASCII, bu aralıktaki uyumlu hale getirir.

'B' '0x42' ya da ikili 0100 0010 (söylediğimiz gibi, ASCII aynı şey). örneğin, Unicode kod noktası için UTF-8 kodlaması sonra olur:

0xxx xxxx  <-- UTF-8 encoding for Unicode code points 0 to 127
*100 0010  <-- Unicode code point 0x42
0100 0010  <-- UTF-8 encoded (exactly the same)

UTF-8 127 yukarıdaki Unicode kod noktaları (ascıı olmayan): kodlama

110x xxxx 10xx xxxx            <-- (from 128 to 2047)
1110 xxxx 10xx xxxx 10xx xxxx  <-- (from 2048 to 65535)
  • önde gelen bit '110' belirtmek için UTF-8 kod çözücü başına bir kod noktası kodlanmış 2 bayt ise '1110' gösterir 3 bayt, 11110 olacağını gösteriyor 4 bayt ve benzeri.
  • iç '10' bayrak bit iç bayt başına sinyali için kullanılır.
  • yine, x Unicode kod noktası değeri kodlama sonra depolandığı alanı işaretlemek.

örneğin 'o' Unicode kod noktası 0xe9 (233).

1110 1001    <-- 0xe9

UTF-8 Bu değer, kodlar, değer 2048, bu nedenle 2 bayt kodlanmış olması gerekenden 127 ve az daha büyük olduğunu belirler:

110x xxxx 10xx xxxx   <-- UTF-8 encoding for Unicode 128-2047
***0 0011 **10 1001   <-- 0xe9
1100 0011 1010 1001   <-- 'é' after UTF-8 encoding
C    3    A    9

UTF-8 sonra 0xe9 Unicode kod noktaları kodlama 0xc3a9 olur. Terminal alır zaten. Eğer terminal ayarlanır deşifre dizeleri kullanarak latin-1 (bir unicode olmayan eski kodlamalar), göreceksin é, çünkü sadece bu yüzden olur 0xc3 latin-1 puan - ve 0xa9 ©.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • grickle

    grickle

    22 AĞUSTOS 2006
  • Kyletiv7

    Kyletiv7

    28 Mayıs 2007
  • Manuel Vizcaino

    Manuel Vizca

    27 Mayıs 2008