Saat menyalurkan output dari program Python, juru bahasa Python menjadi bingung tentang penyandian dan mengaturnya ke None. Ini berarti program seperti ini:
# -*- coding: utf-8 -*-
print u"åäö"
akan berfungsi dengan baik saat dijalankan secara normal, tetapi gagal dengan:
UnicodeEncodeError: 'ascii' codec tidak dapat menyandikan karakter u '\ xa0' di posisi 0: ordinal tidak dalam jangkauan (128)
bila digunakan dalam urutan pipa.
Apa cara terbaik untuk membuat ini berfungsi saat pemipaan? Bisakah saya katakan saja untuk menggunakan pengkodean apa pun shell / filesystem / apa pun yang menggunakan?
Saran yang saya lihat sejauh ini adalah untuk memodifikasi situs Anda.py secara langsung, atau hardcoding defaultencoding menggunakan hack ini:
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"
Apakah ada cara yang lebih baik untuk membuat perpipaan bekerja?
chcp 65001
sebelum menjalankan skrip Anda. Ini dapat memiliki masalah, tetapi seringkali membantu, dan tidak memerlukan banyak pengetikan (kurang dariset PYTHONIOENCODING=utf_8
).setx PYTHONENCODING utf-8
membuatnya permanen jika Anda ingin menyimpan pengetikan.Jawaban:
Kode Anda berfungsi saat dijalankan dalam skrip karena Python mengkodekan output ke apa pun yang menggunakan aplikasi terminal Anda. Jika Anda mengirim pipa, Anda harus menyandikannya sendiri.
Aturan praktisnya adalah: Selalu gunakan Unicode secara internal. Dekode apa yang Anda terima, dan sandi apa yang Anda kirim.
Contoh didaktik lain adalah program Python untuk mengkonversi antara ISO-8859-1 dan UTF-8, membuat semuanya huruf besar di antaranya.
Mengatur pengkodean default sistem adalah ide yang buruk, karena beberapa modul dan pustaka yang Anda gunakan dapat bergantung pada fakta bahwa itu adalah ASCII. Jangan lakukan itu.
sumber
sys.stdout
sepertinya cara yang lebih menyenangkan.PYTHONIOENCODING
jika Anda mengarahkan ulang stdout skrip ke Python 2.Pertama, mengenai solusi ini:
Tidak praktis untuk mencetak secara eksplisit dengan penyandian yang diberikan setiap waktu. Itu akan menjadi berulang dan rawan kesalahan.
Solusi yang lebih baik adalah mengubah
sys.stdout
pada awal program Anda, untuk menyandikan dengan penyandian yang dipilih. Berikut adalah salah satu solusi yang saya temukan di Python: Bagaimana sys.stdout.encoding dipilih? , khususnya komentar oleh "toka":sumber
def myprint(unicodeobj): print unicodeobj.encode('utf-8')
- Anda secara otomatis mendeteksi pengkodean terminal dengan memeriksasys.stdout.encoding
, tetapi Anda harus mempertimbangkan kasus di mana itu beradaNone
(yaitu ketika mengarahkan output ke file) jadi Anda memerlukan fungsi yang terpisah pula.Anda mungkin ingin mencoba mengubah variabel lingkungan "PYTHONIOENCODING" menjadi "utf_8". Saya telah menulis sebuah halaman tentang cobaan saya dengan masalah ini .
Tl; dr dari posting blog:
Memberi anda
sumber
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
. Ini dapat dilakukan dari dalam program python, sehingga pengguna tidak dipaksa untuk mengatur variabel env.PYTHONIOENCODING
tidak berfungsi. Bagaimana byte ditafsirkan sebagai teks didefinisikan oleh lingkungan pengguna . Skrip Anda tidak boleh mengasumsikan dan menentukan lingkungan pengguna pengkodean karakter apa yang digunakan. Jika Python tidak mengambil pengaturan secara otomatis makaPYTHONIOENCODING
dapat diatur untuk skrip Anda. Anda seharusnya tidak membutuhkannya kecuali output diarahkan ke file / pipa.melakukan pekerjaan itu, tetapi tidak dapat mengaturnya di python itu sendiri ...
yang dapat kami lakukan adalah memverifikasi jika tidak mengatur dan memberi tahu pengguna untuk menyetelnya sebelum skrip panggilan dengan:
Perbarui untuk membalas komentar: masalah baru saja ada ketika mengirim pesan ke stdout. Saya menguji dalam Fedora 25 Python 2.7.13
kucing b.py
menjalankan ./b.py
menjalankan ./b.py | kurang
sumber
sys.stdout.encoding
diatur secara otomatis berdasarkan nilaiLC_CTYPE
lokal.Saya memiliki masalah serupa minggu lalu . Itu mudah untuk diperbaiki di IDE saya (PyCharm).
Inilah perbaikan saya:
Mulai dari bilah menu PyCharm: File -> Settings ... -> Editor -> File Encodings, kemudian atur: "IDE Encoding", "Project Encoding" dan "Encoding default untuk file properti" ALL ke UTF-8 dan dia sekarang bekerja seperti pesona.
Semoga ini membantu!
sumber
Versi yang bisa diperdebatkan dari jawaban Craig McQueen.
Pemakaian:
sumber
Saya bisa "mengotomatisasi" itu dengan panggilan ke:
Ya, mungkin untuk mendapatkan loop tak terbatas di sini jika "setenv" ini gagal.
sumber
Saya hanya berpikir saya akan menyebutkan sesuatu di sini yang saya harus menghabiskan waktu lama untuk bereksperimen sebelum saya akhirnya menyadari apa yang sedang terjadi. Ini mungkin sangat jelas bagi semua orang di sini sehingga mereka tidak repot-repot menyebutkannya. Tapi itu akan membantu saya jika mereka melakukannya, maka pada prinsip itu ...!
NB: Saya menggunakan Jython secara khusus, v 2.7, jadi mungkin saja ini tidak berlaku untuk CPython ...
NB2: dua baris pertama file .py saya di sini adalah:
Mekanisme konstruksi string "%" (AKA "interpolasi operator") menyebabkan masalah TAMBAHAN juga ... Jika pengkodean default "lingkungan" adalah ASCII dan Anda mencoba melakukan sesuatu seperti
Anda tidak akan kesulitan menjalankan di Eclipse ... Di Windows CLI (jendela DOS) Anda akan menemukan bahwa penyandiannya adalah kode halaman 850 (OS Windows 7 saya) atau yang serupa, yang setidaknya dapat menangani karakter aksen Eropa, jadi akan bekerja.
juga akan bekerja.
Jika, OTOH, Anda mengarahkan ke file dari CLI, pengkodean stdout akan menjadi None, yang akan menjadi standar ASCII (pada OS saya), yang tidak akan dapat menangani salah satu dari cetakan di atas ... (pengkodean menakutkan kesalahan).
Jadi, Anda mungkin berpikir untuk mengarahkan ulang stdout Anda dengan menggunakan
dan coba jalankan dalam pemipaan CLI ke file ... Anehnya, cetak A di atas akan berfungsi ... Tapi cetak B di atas akan membuang kesalahan penyandian! Namun berikut ini akan berfungsi OK:
Kesimpulan saya datang ke (sementara) adalah bahwa jika sebuah string yang ditentukan untuk menjadi string Unicode menggunakan awalan "u" diajukan ke mekanisme penanganan% tampaknya melibatkan penggunaan pengkodean lingkungan default, terlepas dari apakah Anda telah mengatur stdout untuk mengarahkan ulang!
Bagaimana orang berurusan dengan ini adalah masalah pilihan. Saya akan menyambut pakar Unicode untuk mengatakan mengapa ini terjadi, apakah saya salah dalam beberapa hal, apa solusi yang disukai untuk ini, apakah itu juga berlaku untuk CPython , apakah itu terjadi pada Python 3, dll., Dll.
sumber
"fréd"
urutan byte dan bukan string Unicode, sehinggacodecs.getwriter
pembungkus akan meninggalkannya sendiri. Anda membutuhkan pemimpinu
, ataufrom __future__ import unicode_literals
.Saya mengalami masalah ini dalam aplikasi lawas, dan sulit untuk mengidentifikasi di mana apa yang dicetak. Saya membantu diri saya dengan hack ini:
Di atas skrip saya, test.py:
Perhatikan bahwa ini mengubah SEMUA panggilan untuk mencetak untuk menggunakan penyandian, sehingga konsol Anda akan mencetak ini:
sumber
Di Windows, saya sering mengalami masalah ini ketika menjalankan kode Python dari editor (seperti Sublime Text), tetapi tidak jika menjalankannya dari command-line.
Dalam hal ini, periksa parameter editor Anda. Dalam kasus SublimeText, ini
Python.sublime-build
menyelesaikannya:sumber