Saya mengalami masalah berurusan dengan karakter unicode dari teks yang diambil dari halaman web yang berbeda (di situs yang berbeda). Saya menggunakan BeautifulSoup.
Masalahnya adalah bahwa kesalahan tidak selalu dapat direproduksi; kadang-kadang bekerja dengan beberapa halaman, dan kadang-kadang, itu muntah dengan melempar a UnicodeEncodeError
. Saya telah mencoba hampir semua yang dapat saya pikirkan, namun saya belum menemukan apa pun yang bekerja secara konsisten tanpa melemparkan semacam kesalahan terkait Unicode.
Salah satu bagian dari kode yang menyebabkan masalah ditunjukkan di bawah ini:
agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
Berikut ini adalah jejak tumpukan yang dihasilkan pada BEBERAPA string ketika snipet di atas dijalankan:
Traceback (most recent call last):
File "foobar.py", line 792, in <module>
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)
Saya menduga ini karena beberapa halaman (atau lebih spesifiknya, halaman dari beberapa situs) mungkin dikodekan, sementara yang lain mungkin tidak di-kode. Semua situs berbasis di Inggris dan menyediakan data yang dimaksudkan untuk konsumsi Inggris - sehingga tidak ada masalah yang berkaitan dengan internalisasi atau berurusan dengan teks yang ditulis dalam apa pun selain bahasa Inggris.
Adakah yang punya ide bagaimana menyelesaikan ini sehingga saya dapat memperbaiki masalah ini secara KONSISTEN?
sumber
import os; import locale; os.environ["PYTHONIOENCODING"] = "utf-8"; myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8"); ... print(myText.encode('utf-8', errors='ignore'))
.$ export PYTHONIOENCODING=utf8
Jawaban:
Anda perlu membaca Python Unicode HOWTO . Kesalahan ini adalah contoh pertama .
Pada dasarnya, hentikan penggunaan
str
untuk mengonversi dari unicode ke teks / byte yang disandikan.Sebagai gantinya, gunakan dengan benar
.encode()
untuk menyandikan string:atau bekerja sepenuhnya dalam unicode.
sumber
print
saya utf-8 string saya berfungsi dengan baik. Namun ketika saya mem-pipe output program saya ke file, ia melempar aUnicodeEncodeError
. Bahkan, ketika output diarahkan (ke file atau pipa), saya menemukan bahwasys.stdout.encoding
adalahNone
! Menangani.encode('utf-8')
masalah memecahkan masalah.PYTHONIOENCODING=utf-8
sebagai contoh , cetak string Unicode dan biarkan lingkungan untuk mengatur pengkodean yang diharapkan..encode()
metode untuk memanggil.Ini adalah titik nyeri unicode python klasik! Pertimbangkan yang berikut ini:
Sejauh ini semuanya baik-baik saja, tetapi jika kita sebut str (a), mari kita lihat apa yang terjadi:
Oh celup, itu tidak akan ada gunanya bagi siapa pun! Untuk memperbaiki kesalahan, enkode byte secara eksplisit dengan .encode dan beri tahu python apa codec yang akan digunakan:
Voil \ u00E0!
Masalahnya adalah ketika Anda memanggil str (), python menggunakan pengkodean karakter default untuk mencoba dan menyandikan byte yang Anda berikan, yang dalam kasus Anda terkadang merupakan representasi karakter unicode. Untuk memperbaiki masalah, Anda harus memberi tahu python cara menangani string yang Anda berikan dengan menggunakan .encode ('whatever_unicode'). Biasanya, Anda harus menggunakan utf-8.
Untuk eksposisi yang sangat baik tentang topik ini, lihat pembicaraan PyCon Ned Batchelder di sini: http://nedbatchelder.com/text/unipain.html
sumber
None
nilai.Saya menemukan pekerjaan yang elegan di sekitar bagi saya untuk menghapus simbol dan terus menjaga string sebagai string sebagai berikut:
Penting untuk memperhatikan bahwa menggunakan opsi abaikan berbahaya karena diam-diam menjatuhkan dukungan unicode (dan internasionalisasi) dari kode yang menggunakannya, seperti yang terlihat di sini (convert unicode):
sumber
yourstring = yourstring.encode('utf-8', 'ignore').decode('utf-8')
os.path.join()
, itu kebiasaan yang sangat baik ketika Anda mulai melakukan pemrograman lintas platform. :)baik saya mencoba segalanya tetapi tidak membantu, setelah googling saya pikir berikut dan itu membantu. python 2.7 sedang digunakan.
sumber
if sys.version_info.major < 3:
Masalah halus yang menyebabkan bahkan cetak gagal adalah salah mengatur variabel lingkungan Anda, mis. di sini LC_ALL diatur ke "C". Di Debian mereka tidak menyarankan untuk mengaturnya: Debian wiki di Lokal
sumber
env|grep -E '(LC|LANG)'
.mc
dalam "modus subkulit" (Ctrl-O
) dan saya juga lupa bahwa saya menambahkan alias berikut untuk bash:alias mc="LANG=en_EN.UTF-8 mc"
. Jadi ketika saya mencoba menjalankan skrip yang ditulis dengan buruk yang mengandalkanru_RU.UTF-8
internal, mereka hanya mati. Mencoba banyak hal dari utas ini sebelum saya menemukan masalah sebenarnya. :)Bagi saya, yang berhasil adalah:
Semoga ini bisa membantu seseorang.
sumber
Saya benar-benar menemukan bahwa dalam sebagian besar kasus saya, hanya menghapus karakter-karakter itu jauh lebih sederhana:
sumber
Masalahnya adalah Anda mencoba mencetak karakter unicode, tetapi terminal Anda tidak mendukungnya.
Anda dapat mencoba menginstal
language-pack-en
paket untuk memperbaikinya:yang menyediakan pembaruan data terjemahan Bahasa Inggris untuk semua paket yang didukung (termasuk Python). Instal paket bahasa yang berbeda jika perlu (tergantung karakter mana yang Anda coba cetak).
Pada beberapa distribusi Linux diperlukan untuk memastikan bahwa bahasa Inggris default diatur dengan benar (sehingga karakter unicode dapat ditangani oleh shell / terminal). Terkadang lebih mudah untuk menginstalnya, daripada mengonfigurasinya secara manual.
Kemudian ketika menulis kode, pastikan Anda menggunakan pengkodean yang tepat dalam kode Anda.
Sebagai contoh:
Jika Anda masih mengalami masalah, periksa kembali konfigurasi sistem Anda, seperti:
File lokal Anda (
/etc/default/locale
), yang seharusnya memiliki misatau:
Nilai dari
LANG
/LC_CTYPE
dalam shell.Periksa lokasi yang didukung shell Anda oleh:
Menunjukkan masalah dan solusi dalam VM baru.
Inisialisasi dan berikan VM (mis. Menggunakan
vagrant
):Lihat: kotak Ubuntu yang tersedia ..
Mencetak karakter unicode (seperti tanda merek dagang
™
):Sekarang menginstal
language-pack-en
:Sekarang masalah harus dipecahkan:
Jika tidak, coba perintah berikut:
sumber
language-pack-en
hubungannya dengan Python atau pertanyaan ini? AFAIK, ini mungkin menyediakan terjemahan bahasa ke pesan tetapi tidak ada hubungannya dengan penyandian/etc/locale.gen
untuk memastikan lokal mereka dibangun sebelum menggunakannya?LANG
dari/etc/default/locale
(seperti tidak/etc/locale.gen
ada) dan berlarilocale-gen
, tetapi tidak membantu. Saya tidak yakin apalanguage-pack-en
sebenarnya yang harus dilakukan, karena saya tidak menemukan banyak dokumentasi dan daftar isinya tidak banyak membantu.LANG
/LC_CTYPE
/LC_ALL
sebagai gantinya (misalnya,LANG=C.UTF-8
).Dalam shell:
Temukan lokal UTF-8 yang didukung oleh perintah berikut:
Ekspor, sebelum menjalankan skrip, misalnya:
atau secara manual suka:
Uji dengan mencetak karakter khusus, misalnya
™
:Di atas diuji di Ubuntu.
sumber
Tambahkan baris di bawah ini di awal skrip Anda (atau sebagai baris kedua):
Itulah definisi pengkodean kode sumber python. Info lebih lanjut dalam PEP 263 .
sumber
Berikut adalah pengulangan dari beberapa jawaban yang disebut "cop out". Ada situasi di mana membuang karakter / string yang merepotkan adalah solusi yang baik, meskipun ada protes yang disuarakan di sini.
Mengujinya:
Hasil:
Saran: Anda mungkin ingin menamai fungsi ini
toAscii
sebagai gantinya? Itu masalah preferensi.Ini ditulis untuk Python 2. Untuk Python 3, saya yakin Anda ingin menggunakan
bytes(obj,"ascii")
daripadastr(obj)
. Saya belum menguji ini, tetapi saya akan pada beberapa titik dan merevisi jawabannya.sumber
Saya selalu meletakkan kode di bawah ini dalam dua baris pertama dari file python:
sumber
Fungsi pembantu sederhana ditemukan di sini .
sumber
backslashreplace
handler error:u'\xa0'.encode('ascii', 'backslashreplace')
. Meskipun Anda harus menghindari representasi tersebut dan mengonfigurasi lingkungan Anda untuk menerima karakter non-ascii sebagai gantinya - ini adalah 2016!Cukup tambahkan ke penyandiaksaraan variabel ('utf-8')
sumber
Silakan buka terminal dan jalankan perintah di bawah ini:
sumber
Saya hanya menggunakan yang berikut ini:
Periksa apa yang dikatakan dokumentasi tentangnya:
Menyelesaikannya untukku. Sederhana dan mudah.
sumber
Solusi di bawah ini bekerja untuk saya, Baru ditambahkan
(mewakili string sebagai unicode) sebelum string saya.
sumber
Sayangnya ini berfungsi di Python 3 setidaknya ...
Python 3
Kadang-kadang kesalahan ada dalam variabel lingkungan dan mengkondisikannya
di mana kesalahan diabaikan dalam penyandian.
sumber
Saya baru saja mengalami masalah ini, dan Google membawa saya ke sini, jadi hanya untuk menambahkan solusi umum di sini, inilah yang bekerja untuk saya:
Saya mendapat ide ini setelah membaca presentasi Ned .
Saya tidak mengklaim sepenuhnya mengerti mengapa ini berhasil. Jadi jika ada yang bisa mengedit jawaban ini atau memberikan komentar untuk menjelaskan, saya akan menghargainya.
sumber
type
nilainya? sebelum dan sesudah ini? Saya pikir mengapa yang berhasil adalah bahwa dengan melakukanunic += value
yang sama sepertiunic = unic + value
Anda menambahkan string dan unicode, di mana python kemudian mengasumsikan unicode untuk resultanunic
yaitu jenis yang lebih tepat (pikirkan ketika Anda melakukan inia = float(1) + int(1)
,a
menjadi pelampung) dan kemudianvalue = unic
menunjukvalue
keunic
objek baru yang kebetulan unicode.Kami menemukan kesalahan ini saat menjalankan
manage.py migrate
di Django dengan perlengkapan lokal.Sumber kami berisi
# -*- coding: utf-8 -*-
deklarasi, MySQL telah dikonfigurasi dengan benar untuk utf8 dan Ubuntu memiliki paket bahasa dan nilai-nilai yang sesuai di dalamnya/etc/default/locale
.Masalahnya hanyalah bahwa wadah Django (kami menggunakan buruh pelabuhan) tidak ada
LANG
env var.Mengatur
LANG
keen_US.UTF-8
dan memulai kembali wadah sebelum menjalankan migrasi kembali memperbaiki masalah.sumber
Banyak jawaban di sini (@agf dan @Andbdrew misalnya) telah membahas aspek paling langsung dari pertanyaan OP.
Namun, saya pikir ada satu aspek halus namun penting yang sebagian besar telah diabaikan dan yang penting bagi semua orang yang seperti saya berakhir di sini ketika mencoba untuk memahami penyandian dalam Python: Python 2 vs Python 3 pengelolaan representasi karakter sangat berbeda . Saya merasa seperti sebagian besar kebingungan di luar sana ada hubungannya dengan orang-orang yang membaca tentang penyandian dengan Python tanpa menyadari versi.
Saya menyarankan siapa pun yang tertarik untuk memahami akar penyebab masalah OP untuk memulai dengan membaca pengantar Spolsky untuk representasi karakter dan Unicode dan kemudian pindah ke Batchelder pada Unicode di Python 2 dan Python 3.
sumber
Cobalah untuk menghindari konversi variabel ke str (variabel). Terkadang, ini dapat menyebabkan masalah.
Kiat sederhana yang harus dihindari:
Contoh di atas juga akan menyelesaikan kesalahan Encode.
sumber
Jika Anda memiliki sesuatu seperti
packet_data = "This is data"
kemudian lakukan ini di baris berikutnya, tepat setelah menginisialisasipacket_data
:sumber
Perbarui untuk python 3.0 dan yang lebih baru. Coba yang berikut ini di editor python:
Ini menetapkan pengkodean lokal default sistem ke format UTF-8.
Lebih banyak dapat dibaca di sini di PEP 538 - Memaksa lokal warisan C ke lokal berbasis UTF-8 .
sumber
Saya mengalami masalah ini untuk mencoba menampilkan karakter Unicode
stdout
, tetapi dengansys.stdout.write
, alih-alih mencetak (sehingga saya dapat mendukung keluaran ke file yang berbeda juga).Dari dokumentasi BeautifulSoup sendiri , saya menyelesaikan ini dengan perpustakaan codec:
sumber
Masalah ini sering terjadi ketika proyek Django menggunakan Apache. Karena Apache menetapkan variabel lingkungan LANG = C di / etc / sysconfig / httpd. Cukup buka file dan komentar (atau ubah ke flavior Anda) pengaturan ini. Atau gunakan opsi lang dari perintah WSGIDaemonProcess, dalam hal ini Anda akan dapat mengatur variabel lingkungan LANG yang berbeda ke virtualhosts yang berbeda.
sumber
Solusi yang disarankan tidak bekerja untuk saya, dan saya bisa hidup dengan membuang semua karakter non ascii, jadi
yang membuat saya kehilangan sesuatu.
sumber
Ini akan berhasil:
Keluaran:
sumber