Pertanyaan UnicodeEncodeError: 'ascii' codec tidak dapat menyandikan karakter u '\ xa0' pada posisi 20: ordinal tidak dalam jangkauan (128)


Saya mengalami masalah saat berurusan dengan karakter unicode dari teks yang diambil dari halaman web yang berbeda (di situs yang berbeda). Saya menggunakan BeautifulSoup.

Masalahnya adalah kesalahan itu tidak selalu dapat direproduksi; kadang-kadang berfungsi dengan beberapa halaman, dan kadang-kadang, barfs dengan melempar a UnicodeEncodeError. Saya telah mencoba hampir semua yang dapat saya pikirkan, namun saya belum menemukan apa pun yang bekerja secara konsisten tanpa membuang semacam kesalahan terkait Unicode.

Salah satu bagian 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 tumpukan jejak yang dihasilkan pada beberapa string ketika cuplikan 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 bahwa ini karena beberapa halaman (atau lebih spesifik, halaman dari beberapa situs) dapat dikodekan, sementara yang lain mungkin tidak dienkode. Semua situs tersebut berbasis di Inggris dan memberikan data yang dimaksudkan untuk konsumsi Inggris - jadi tidak ada masalah yang berkaitan dengan internalisasi atau berurusan dengan teks yang ditulis dalam bahasa selain bahasa Inggris.

Adakah yang punya ide bagaimana cara mengatasi ini sehingga saya bisa KONSISTEN memperbaiki masalah ini?


937
2018-03-30 12:06


asal


Jawaban:


Anda perlu membaca Python Unicode HOWTO. Kesalahan ini adalah contoh pertama.

Pada dasarnya, berhenti menggunakan str untuk mengkonversi dari unicode ke teks / byte yang dikodekan.

Sebaliknya, gunakan dengan benar .encode() untuk menyandikan string:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

atau berfungsi sepenuhnya dalam unicode.


1052
2018-03-30 12:21



Ini adalah titik sakit unicode python klasik! Pertimbangkan yang berikut ini:

a = u'bats\u00E0'
print a
 => batsà

Sejauh ini semua baik, tetapi jika kita memanggil str (a), mari kita lihat apa yang terjadi:

str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

Oh dip, itu tidak akan ada gunanya! Untuk memperbaiki kesalahan, lakukan enkode byte secara eksplisit dengan .encode dan beri tahu python codec apa yang digunakan:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil \ u00E0!

Masalahnya adalah bahwa ketika Anda memanggil str (), python menggunakan pengkodean karakter default untuk mencoba dan menyandikan byte yang Anda berikan, yang dalam kasus Anda terkadang merupakan representasi dari karakter unicode. Untuk memperbaiki masalah, Anda harus memberi tahu python cara menangani string yang Anda berikan dengan menggunakan .encode ('whatever_unicode'). Sebagian besar waktu, Anda harus baik-baik saja menggunakan utf-8.

Untuk penjelasan yang sangat bagus tentang topik ini, lihat pidato PyCon Ned Batchelder di sini: http://nedbatchelder.com/text/unipain.html


366
2018-03-30 12:25



Saya menemukan karya yang elegan di sekitar saya untuk menghapus simbol dan terus menyimpan string sebagai string sebagai berikut:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

Sangat penting untuk memperhatikan bahwa menggunakan opsi abaikan adalah berbahaya karena secara diam-diam menghapus dukungan unicode (dan internasionalisasi) dari kode yang menggunakannya, seperti yang terlihat di sini (ubah unicode):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'

165
2017-08-20 10:13



baik saya mencoba segalanya tetapi tidak membantu, setelah googling di sekitar saya pikir berikut ini dan itu membantu. python 2.7 sedang digunakan.

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')

107
2017-09-02 13:10



Masalah halus yang menyebabkan cetak gagal adalah karena variabel lingkungan Anda salah, mis. di sini LC_ALL diatur ke "C". Di Debian mereka tidak menyarankan pengaturannya: Wiki Debian di Lokal

$ echo $LANG
en_US.utf8
$ echo $LC_ALL 
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà

71
2017-12-02 17:58



Saya benar-benar menemukan bahwa dalam sebagian besar kasus saya, menghapus karakter tersebut jauh lebih sederhana:

s = mystring.decode('ascii', 'ignore')

26
2017-11-01 13:44



Bagi saya, yang berhasil adalah:

BeautifulSoup(html_text,from_encoding="utf-8")

Semoga ini bisa membantu seseorang.


24
2018-01-26 14:53



Tambahkan baris di bawah ini di awal skrip Anda (atau sebagai baris kedua):

# -*- coding: utf-8 -*-

Itu definisi dari penyandian kode sumber python. Info selengkapnya di PEP 263.


16
2017-08-08 10:17



Masalahnya adalah Anda mencoba mencetak karakter unicode, tetapi terminal Anda tidak mendukungnya.

Anda dapat mencoba menginstal language-pack-en paket untuk memperbaikinya:

sudo apt-get install language-pack-en

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 standar lokal sudah diatur dengan benar (sehingga karakter unicode dapat ditangani oleh shell / terminal). Terkadang lebih mudah untuk menginstalnya, daripada mengonfigurasinya secara manual.

Kemudian saat menulis kode, pastikan Anda menggunakan pengkodean yang tepat dalam kode Anda.

Sebagai contoh:

open(foo, encoding='utf-8')

Jika Anda masih mengalami masalah, periksa kembali konfigurasi sistem Anda, seperti:

  • File lokal Anda (/etc/default/locale), yang seharusnya memiliki misalnya

    LANG="en_US.UTF-8"
    LC_ALL="en_US.UTF-8"
    
  • Nilai dari LANG/LC_CTYPE di shell.

  • Periksa lokasi mana yang didukung oleh shell Anda dengan:

    locale -a | grep "UTF-8"
    

Mendemonstrasikan masalah dan solusi dalam VM segar.

  1. Menginisialisasi dan menyediakan VM (mis. Menggunakan vagrant):

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
    

    Lihat: tersedia kotak Ubuntu..

  2. Mencetak karakter unicode (seperti tanda merek dagang seperti ):

    $ python -c 'print(u"\u2122");'
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
    
  3. Sekarang menginstal language-pack-en:

    $ sudo apt-get -y install language-pack-en
    The following extra packages will be installed:
      language-pack-en-base
    Generating locales...
      en_GB.UTF-8... /usr/sbin/locale-gen: done
    Generation complete.
    
  4. Sekarang masalah terpecahkan:

    $ python -c 'print(u"\u2122");'
    
    

14
2017-08-13 12:07



Berikut ini adalah pengulangan beberapa jawaban "cop out" lainnya. Ada situasi di mana hanya membuang karakter / string yang merepotkan adalah solusi yang baik, meskipun protes disuarakan di sini.

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

Mengujinya:

if __name__ == '__main__': 
    print safeStr( 1 ) 
    print safeStr( "test" ) 
    print u'98\xb0'
    print safeStr( u'98\xb0' )

Hasil:

1
test
98°
98

Saran: Anda mungkin ingin memberi nama fungsi ini toAscii sebagai gantinya? Itu masalah kesukaan.


10
2017-09-26 19:23