Dari shell Python 2.6:
>>> import sys
>>> print sys.getdefaultencoding()
ascii
>>> print u'\xe9'
é
>>>
Saya berharap memiliki beberapa omong kosong atau Kesalahan setelah pernyataan cetak, karena karakter "é" bukan bagian dari ASCII dan saya belum menentukan penyandian. Saya kira saya tidak mengerti apa artinya pengkodean default ASCII.
EDIT
Saya memindahkan hasil edit ke bagian Jawaban dan menerimanya seperti yang disarankan.
'\xe9'
di terminal yang dikonfigurasi untuk UTF-8 tidak akan mencetaké
. Ini akan mencetak karakter pengganti (biasanya tanda tanya) karena\xe9
bukan urutan UTF-8 yang valid (tidak ada dua byte yang seharusnya mengikuti byte terkemuka itu). Ini pasti tidak akan ditafsirkan sebagai Latin-1 sebagai gantinya.\xe9
untuk mencetaké
.Jawaban:
Berkat potongan-potongan dari berbagai balasan, saya pikir kita bisa menjahit penjelasan.
Dengan mencoba mencetak string unicode, u '\ xe9', Python secara implisit mencoba untuk menyandikan string itu menggunakan skema penyandian yang saat ini disimpan di sys.stdout.encoding. Python sebenarnya mengambil pengaturan ini dari lingkungannya. Jika itu tidak dapat menemukan pengkodean yang tepat dari lingkungan, hanya kemudian kembali ke standarnya , ASCII.
Sebagai contoh, saya menggunakan bash shell yang secara default encoding ke UTF-8. Jika saya memulai Python dari itu, ia mengambil dan menggunakan pengaturan itu:
Mari sesaat keluar dari shell Python dan atur lingkungan bash dengan beberapa penyandian palsu:
Kemudian mulai shell python lagi dan verifikasi bahwa memang mengembalikan ke ascii default.
Bingo!
Jika sekarang Anda mencoba untuk mengeluarkan beberapa karakter unicode di luar ascii Anda akan mendapatkan pesan kesalahan yang bagus
Ayo keluar dari Python dan buang bash shell.
Kami sekarang akan mengamati apa yang terjadi setelah Python mengeluarkan string. Untuk ini pertama-tama kita akan memulai bash shell dalam terminal grafik (saya menggunakan Terminal Gnome) dan kami akan mengatur terminal untuk mendekode output dengan ISO-8859-1 alias latin-1 (terminal grafik biasanya memiliki opsi untuk Mengatur Karakter Pengkodean di salah satu menu dropdown mereka). Perhatikan bahwa ini tidak mengubah pengkodean lingkungan shell yang sebenarnya , itu hanya mengubah cara terminal itu sendiri akan mendekode output yang diberikan, sedikit seperti browser web. Karena itu Anda dapat mengubah pengkodean terminal, secara independen dari lingkungan shell. Mari kita mulai Python dari shell dan verifikasi bahwa sys.stdout.encoding diatur ke pengkodean lingkungan shell (UTF-8 untuk saya):
(1) python mengeluarkan string biner, terminal menerimanya dan mencoba mencocokkan nilainya dengan peta karakter latin-1. Dalam bahasa latin-1, 0xe9 atau 233 menghasilkan karakter "é" dan itulah yang ditampilkan terminal.
(2) python mencoba menyandikan string Unicode secara implisit dengan skema apa pun yang saat ini ditetapkan dalam sys.stdout.encoding, dalam hal ini "UTF-8". Setelah pengkodean UTF-8, string biner yang dihasilkan adalah '\ xc3 \ xa9' (lihat penjelasan selanjutnya). Terminal menerima aliran seperti itu dan mencoba untuk men-decode 0xc3a9 menggunakan latin-1, tetapi latin-1 beralih dari 0 ke 255 dan karenanya, hanya mendekode stream 1 byte pada satu waktu. 0xc3a9 panjangnya 2 byte, oleh karena itu decoder latin-1 menerjemahkannya sebagai 0xc3 (195) dan 0xa9 (169) dan menghasilkan 2 karakter: Ã dan ©.
(3) python mengkodekan titik kode unicode u '\ xe9' (233) dengan skema latin-1. Ternyata rentang kode titik latin-1 adalah 0-255 dan menunjuk ke karakter yang sama persis dengan Unicode dalam rentang itu. Oleh karena itu, titik kode Unicode dalam rentang itu akan menghasilkan nilai yang sama ketika dikodekan dalam latin-1. Jadi u '\ xe9' (233) yang dikodekan dalam latin-1 juga akan menghasilkan string biner '\ xe9'. Terminal menerima nilai itu dan mencoba mencocokkannya pada peta karakter latin-1. Sama seperti kasus (1), ia menghasilkan "é" dan itulah yang ditampilkan.
Sekarang mari kita ubah pengaturan penyandian terminal ke UTF-8 dari menu dropdown (seperti Anda akan mengubah pengaturan penyandian browser web Anda). Tidak perlu menghentikan Python atau memulai ulang shell. Pengkodean terminal sekarang cocok dengan Python. Mari kita coba mencetak lagi:
(4) python menampilkan string biner apa adanya. Terminal mencoba untuk men-decode aliran itu dengan UTF-8. Tetapi UTF-8 tidak memahami nilai 0xe9 (lihat penjelasan selanjutnya) dan karena itu tidak dapat mengubahnya menjadi titik kode unicode. Tidak ditemukan titik kode, tidak ada karakter yang dicetak.
(5) python mencoba menyandikan string Unicode secara implisit dengan apa pun yang ada di sys.stdout.encoding. Masih "UTF-8". String biner yang dihasilkan adalah '\ xc3 \ xa9'. Terminal menerima aliran dan mencoba untuk memecahkan kode 0xc3a9 juga menggunakan UTF-8. Ini menghasilkan kembali nilai kode 0xe9 (233), yang pada peta karakter Unicode menunjuk ke simbol "é". Terminal menampilkan "é".
(6) python mengkodekan string unicode dengan latin-1, menghasilkan string biner dengan nilai yang sama '\ xe9'. Sekali lagi, untuk terminal ini hampir sama dengan case (4).
Kesimpulan: - Python menampilkan string non-unicode sebagai data mentah, tanpa mempertimbangkan penyandian defaultnya. Terminal kebetulan menampilkannya jika pengkodeannya saat ini cocok dengan data. - Python mengeluarkan string Unicode setelah menyandikannya menggunakan skema yang ditentukan dalam sys.stdout.encoding. - Python mendapatkan pengaturan itu dari lingkungan shell. - terminal menampilkan output sesuai dengan pengaturan pengkodeannya sendiri. - Pengkodean terminal independen dari shell.
Lebih detail tentang unicode, UTF-8 dan latin-1:
Unicode pada dasarnya adalah tabel karakter di mana beberapa tombol (titik kode) telah secara konvensional ditugaskan untuk menunjuk ke beberapa simbol. misalnya dengan konvensi, telah diputuskan bahwa kunci 0xe9 (233) adalah nilai yang menunjuk ke simbol 'é'. ASCII dan Unicode menggunakan titik kode yang sama dari 0 hingga 127, seperti halnya latin-1 dan Unicode dari 0 hingga 255. Artinya, 0x41 menunjuk ke 'A' di ASCII, latin-1 dan Unicode, 0xc8 menunjuk ke 'Ü' di latin-1 dan Unicode, 0xe9 menunjuk ke 'é' dalam latin-1 dan Unicode.
Saat bekerja dengan perangkat elektronik, titik kode Unicode memerlukan cara yang efisien untuk direpresentasikan secara elektronik. Tentang itulah skema penyandian. Berbagai skema pengkodean Unicode ada (utf7, UTF-8, UTF-16, UTF-32). Pendekatan pengkodean yang paling intuitif dan lurus ke depan adalah dengan hanya menggunakan nilai titik kode dalam peta Unicode sebagai nilai untuk bentuk elektroniknya, tetapi Unicode saat ini memiliki lebih dari satu juta titik kode, yang berarti bahwa beberapa di antaranya memerlukan 3 byte untuk menjadi menyatakan. Untuk bekerja secara efisien dengan teks, pemetaan 1 ke 1 akan agak tidak praktis, karena akan mengharuskan semua titik kode disimpan dalam jumlah ruang yang persis sama, dengan minimal 3 byte per karakter, terlepas dari kebutuhan mereka yang sebenarnya.
Sebagian besar skema pengkodean memiliki kekurangan mengenai persyaratan ruang, yang paling ekonomis tidak mencakup semua poin kode unicode, misalnya ascii hanya mencakup 128 pertama, sedangkan latin-1 mencakup 256 pertama. Lainnya yang mencoba menjadi lebih komprehensif akhirnya juga menjadi boros, karena mereka membutuhkan lebih banyak byte daripada yang diperlukan, bahkan untuk karakter "murah" yang umum. UTF-16 misalnya, menggunakan minimal 2 byte per karakter, termasuk yang berada dalam rentang ascii ('B' yang 65, masih membutuhkan 2 byte penyimpanan di UTF-16). UTF-32 bahkan lebih boros karena menyimpan semua karakter dalam 4 byte.
UTF-8 secara cerdik menyelesaikan dilema, dengan skema yang dapat menyimpan titik kode dengan jumlah variabel ruang byte. Sebagai bagian dari strategi pengkodeannya, UTF-8 bertali poin kode dengan bit bendera yang menunjukkan (mungkin untuk decoder) persyaratan ruang mereka dan batas-batasnya.
Pengkodean poin kode unicode UTF-8 dalam rentang ascii (0-127):
mis. Titik kode Unicode untuk 'B' adalah '0x42' atau 0100 0010 dalam biner (seperti yang kami katakan, itu sama di ASCII). Setelah encoding di UTF-8 menjadi:
Pengkodean poin kode Unicode UTF-8 di atas 127 (non-ascii):
misalnya 'é' Titik kode Unicode adalah 0xe9 (233).
Ketika UTF-8 mengkodekan nilai ini, ini menentukan bahwa nilainya lebih besar dari 127 dan kurang dari 2048, oleh karena itu harus dikodekan dalam 2 byte:
Kode Unicode 0xe9 menunjuk setelah pengkodean UTF-8 menjadi 0xc3a9. Persis bagaimana terminal menerimanya. Jika terminal Anda diatur untuk mendekodekan string menggunakan latin-1 (salah satu pengkodean warisan non-unicode), Anda akan melihat à ©, karena kebetulan 0xc3 dalam bahasa latin-1 menunjuk ke à dan 0xa9 ke ©.
sumber
Ketika karakter Unicode dicetak ke stdout,
sys.stdout.encoding
digunakan. Karakter non-Unicode diasumsikan beradasys.stdout.encoding
dan baru saja dikirim ke terminal. Di sistem saya (Python 2):sys.getdefaultencoding()
hanya digunakan ketika Python tidak memiliki opsi lain.Perhatikan bahwa Python 3.6 atau yang lebih baru mengabaikan penyandian pada Windows dan menggunakan Unicode API untuk menulis Unicode ke terminal. Tidak ada peringatan UnicodeEncodeError dan karakter yang benar ditampilkan jika font mendukungnya. Bahkan jika font tidak mendukungnya, karakter masih dapat dipotong-n-paste dari terminal ke aplikasi dengan font yang mendukung dan itu akan benar. Meningkatkan!
sumber
Python REPL mencoba mengambil pengodean apa yang digunakan dari lingkungan Anda. Jika ia menemukan sesuatu yang waras maka itu semua hanya berfungsi. Itu ketika ia tidak tahu apa yang terjadi sehingga ia keluar.
sumber
TypeError: readonly attribute
2.7.2Anda telah menentukan penyandian dengan memasukkan string Unicode eksplisit. Bandingkan hasil tidak menggunakan
u
awalan.Dalam kasus
\xe9
Python mengasumsikan pengkodean default Anda (Ascii), sehingga mencetak ... sesuatu yang kosong.sumber
Ini bekerja untuk saya:
sumber
Sesuai dengan pengkodean dan konversi string Python default / implisit :
print
ingunicode
, ituencode
dengan<file>.encoding
.encoding
tidak diatur,unicode
secara implisit dikonversi kestr
(karena codec untuk itusys.getdefaultencoding()
, yaituascii
, setiap karakter nasional akan menyebabkan aUnicodeEncodeError
)encoding
disimpulkan dari lingkungan. Ini biasanya mengaturtty
aliran fot (dari pengaturan lokal terminal), tetapi kemungkinan tidak diatur untuk pipaprint u'\xe9'
kemungkinan berhasil ketika output ke terminal, dan gagal jika diarahkan. Solusi untukencode()
string dengan pengkodean yang diinginkan sebelumprint
.print
ingstr
, byte dikirim ke aliran apa adanya. Mesin terbang apa yang ditunjukkan terminal akan tergantung pada pengaturan lokalnya.sumber