Saya telah melihat beberapa skrip py yang menggunakan ini di bagian atas skrip. Dalam kasus apa seseorang harus menggunakannya?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Saya telah melihat beberapa skrip py yang menggunakan ini di bagian atas skrip. Dalam kasus apa seseorang harus menggunakannya?
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
Jawaban:
Sesuai dokumentasi: Ini memungkinkan Anda untuk beralih dari ASCII default ke penyandian lain seperti UTF-8, yang akan digunakan oleh runtime Python setiap kali harus mendekode buffer string ke unicode.
Fungsi ini hanya tersedia pada waktu mulai Python, ketika Python memindai lingkungan. Itu harus disebut dalam modul sistem-lebar sitecustomize.py
,, Setelah modul ini dievaluasi, setdefaultencoding()
fungsi dihapus dari sys
modul.
Satu-satunya cara untuk benar-benar menggunakannya adalah dengan retas retas yang mengembalikan atribut.
Juga, penggunaan sys.setdefaultencoding()
selalu tidak disarankan , dan telah menjadi larangan di py3k. Pengkodean py3k adalah terprogram untuk "utf-8" dan mengubahnya menimbulkan kesalahan.
Saya menyarankan beberapa petunjuk untuk membaca:
sys.stdout
ketika memiliki None
pengkodean, seperti ketika mengarahkan output dari program Python).
sys.setdefaultencoding()
selalu tidak disarankan"
UTF-8
. LC_ALL=en_US.UTF-8 python3 -c 'import sys; print(sys.stdout.encoding)'
memberi UTF-8
tetapi LC_ALL=C python3 -c 'import sys; print(sys.stdout.encoding)'
memberi ANSI_X3.4-1968
(atau mungkin sesuatu yang lain)
Jawabannya TIDAK PERNAH ! (kecuali jika Anda benar-benar tahu apa yang Anda lakukan)
9/10 kali solusinya dapat diselesaikan dengan pemahaman yang tepat tentang pengkodean / decoding.
1/10 orang memiliki lokal atau lingkungan yang tidak didefinisikan dengan benar dan perlu mengatur:
PYTHONIOENCODING="UTF-8"
di lingkungan mereka untuk memperbaiki masalah pencetakan konsol.
(dipukul untuk menghindari penggunaan kembali) mengubah pengkodean / dekode default yang digunakan setiap kali Python 2.x perlu mengubah Unicode () ke str () (dan sebaliknya) dan pengkodean tidak diberikan. Yaitu:sys.setdefaultencoding("utf-8")
str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC")
Dalam Python 2.x, penyandian default diatur ke ASCII dan contoh di atas akan gagal dengan:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
(Konsol saya dikonfigurasi sebagai UTF-8, jadi "€" = '\xe2\x82\xac'
, karenanya pengecualian pada \xe2
)
atau
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
akan memungkinkan ini bekerja untuk saya , tetapi tidak akan selalu berfungsi untuk orang yang tidak menggunakan UTF-8. Default ASCII memastikan bahwa asumsi pengkodean tidak dimasukkan ke dalam kodesys.setdefaultencoding("utf-8")
juga memiliki efek samping muncul untuk memperbaiki sys.setdefaultencoding("utf-8")
sys.stdout.encoding
, digunakan saat mencetak karakter ke konsol. Python menggunakan lokal pengguna (Linux / OS X / Un * x) atau codepage (Windows) untuk mengatur ini. Kadang-kadang, lokal pengguna rusak dan hanya perlu PYTHONIOENCODING
memperbaiki pengkodean konsol .
Contoh:
$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()
$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€
Orang-orang telah mengembangkan terhadap Python 2.x selama 16 tahun dengan pemahaman bahwa penyandian default adalah ASCII. UnicodeError
metode penanganan pengecualian telah ditulis untuk menangani konversi string ke Unicode pada string yang ternyata mengandung non-ASCII.
Dari https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/
def welcome_message(byte_string):
try:
return u"%s runs your business" % byte_string
except UnicodeError:
return u"%s runs your business" % unicode(byte_string,
encoding=detect_encoding(byte_string))
print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))
Sebelum menetapkan defaultencoding, kode ini tidak akan dapat men-decode "Å" dalam encoding ascii dan kemudian akan memasukkan pengendali pengecualian untuk menebak encoding dan mengubahnya dengan benar menjadi unicode. Mencetak: Angstrom (Å®) menjalankan bisnis Anda. Setelah Anda menetapkan defaultencoding ke utf-8 kode akan menemukan bahwa byte_string dapat diartikan sebagai utf-8 dan itu akan memotong-motong data dan mengembalikan ini sebagai gantinya: Angstrom (Ů) menjalankan bisnis Anda.
Mengubah apa yang seharusnya konstan akan memiliki efek dramatis pada modul yang Anda andalkan. Lebih baik memperbaiki data yang masuk dan keluar dari kode Anda.
Sementara pengaturan defaultencoding ke UTF-8 bukan penyebab utama dalam contoh berikut, ini menunjukkan bagaimana masalah ditutup dan bagaimana, ketika input encoding berubah, kode tersebut terputus dengan cara yang tidak jelas: UnicodeDecodeError: codec 'utf8' dapat mendekode byte 0x80 di posisi 3131: byte awal tidak valid
sys.setdefaultencoding("utf-8")
dalamnya, ada baiknya membuat kode berperilaku lebih seperti Python 3. Sekarang 2017. Bahkan ketika Anda menulis jawabannya pada tahun 2015, saya pikir sudah lebih baik untuk melihat ke depan daripada ke belakang. Itu sebenarnya solusi paling sederhana bagi saya, ketika saya menemukan kode saya berperilaku berbeda di Python 2 tergantung pada apakah output diarahkan (masalah yang sangat buruk untuk Python 2). Tak perlu dikatakan, saya sudah punya # coding: utf-8
, dan saya tidak perlu ada solusi untuk Python 3 (saya benar-benar harus menutupi setdefaultencoding
cek menggunakan versi).
sys.setdefaultencoding("utf-8")
tidak membuat kode Py 2.x Anda kompatibel dengan Python 3. Juga tidak memperbaiki modul eksternal yang menganggap pengkodean default adalah ASCII. Membuat kode Anda kompatibel dengan Python 3 sangat sederhana dan tidak memerlukan peretasan jahat ini. Misalnya mengapa ini menyebabkan masalah yang sangat nyata, lihat pengalaman saya dengan Amazon mengacaukan asumsi ini: stackoverflow.com/questions/39465220/…
PYTHONIOENCODING="UTF-8"
membantu lingkungan Python2.7 Django-1.11 saya. Terima kasih.
detect_encoding
.
detect_encoding
adalah metode yang bisa mendeteksi pengkodean string berdasarkan petunjuk bahasa.
#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u
chmod +x test.py
./test.py
moçambique
moçambique
./test.py > output.txt
Traceback (most recent call last):
File "./test.py", line 5, in <module>
print u
UnicodeEncodeError: 'ascii' codec can't encode character
u'\xe7' in position 2: ordinal not in range(128)
pada shell bekerja, mengirim ke sdtout tidak, jadi itu adalah satu solusi, untuk menulis ke stdout
Saya membuat pendekatan lain, yang tidak berjalan jika sys.stdout.encoding tidak mendefinisikan, atau dengan kata lain, perlu ekspor PYTHONIOENCODING = UTF-8 terlebih dahulu untuk menulis ke stdout.
import sys
if (sys.stdout.encoding is None):
print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
exit(1)
jadi, dengan menggunakan contoh yang sama:
export PYTHONIOENCODING=UTF-8
./test.py > output.txt
akan bekerja
Bahaya pertama terletak pada reload(sys)
.
Ketika Anda memuat ulang modul, Anda sebenarnya mendapatkan dua salinan dari modul di runtime Anda. Modul lama adalah objek Python seperti yang lainnya, dan tetap hidup selama ada referensi untuk itu. Jadi, setengah dari objek akan menunjuk ke modul lama, dan setengah ke yang baru. Ketika Anda membuat beberapa perubahan, Anda tidak akan pernah melihatnya datang ketika beberapa objek acak tidak melihat perubahan:
(This is IPython shell)
In [1]: import sys
In [2]: sys.stdout
Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
In [3]: reload(sys)
<module 'sys' (built-in)>
In [4]: sys.stdout
Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
In [11]: import IPython.terminal
In [14]: IPython.terminal.interactiveshell.sys.stdout
Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
Sekarang, sys.setdefaultencoding()
tepat
Semua yang dipengaruhinya adalah konversi implisitstr<->unicode
. Sekarang, utf-8
apakah penyandian paling baik di planet ini (kompatibel dengan ASCII dan yang lainnya), konversi sekarang "hanya berfungsi", apa yang mungkin salah?
Yah, apapun. Dan itu adalah bahayanya.
UnicodeError
yang dilemparkan untuk input non-ASCII, atau melakukan transcoding dengan penangan kesalahan, yang sekarang menghasilkan hasil yang tidak terduga. Dan karena semua kode diuji dengan pengaturan default, Anda benar-benar berada di wilayah "tidak didukung" di sini , dan tidak ada yang memberi Anda jaminan tentang bagaimana kode mereka akan berperilaku.