u '\ ufeff' dalam string Python

152

Saya mendapatkan kesalahan dengan derai berikut:

UnicodeEncodeError: 'ascii' codec can't encode character u'\ufeff' in position 155: ordinal not in range(128)

Tidak yakin apa u'\ufeff'itu, itu muncul ketika saya sedang menggores web. Bagaimana saya bisa memperbaiki situasi? The .replace()Metode string tidak bekerja di dalamnya.

James Hallen
sumber
6
Dari mana input ini berasal? Apa yang kamu coba lakukan? Harap sertakan kode Python Anda.
7
Kebetulan, saya menemukan bahwa .replace () berfungsi dengan python modern jika saya ingat indikator unicode: s.replace (u '\ ufeff', '')
Doug Bradshaw
@ DougBradshaw ketika Anda mengatakan "python modern", maksud Anda, 2.7+ atau 3.0+?
teewuane
Poin yang bagus. Artinya, 2.7+.
Doug Bradshaw

Jawaban:

184

Karakter Unicode U+FEFFadalah tanda urutan byte, atau BOM, dan digunakan untuk memberi tahu perbedaan antara pengkodean UTF-16 big dan endian. Jika Anda mendekode halaman web menggunakan codec yang tepat, Python akan menghapusnya untuk Anda. Contoh:

#!python2
#coding: utf8
u = u'ABC'
e8 = u.encode('utf-8')        # encode without BOM
e8s = u.encode('utf-8-sig')   # encode with BOM
e16 = u.encode('utf-16')      # encode with BOM
e16le = u.encode('utf-16le')  # encode without BOM
e16be = u.encode('utf-16be')  # encode without BOM
print 'utf-8     %r' % e8
print 'utf-8-sig %r' % e8s
print 'utf-16    %r' % e16
print 'utf-16le  %r' % e16le
print 'utf-16be  %r' % e16be
print
print 'utf-8  w/ BOM decoded with utf-8     %r' % e8s.decode('utf-8')
print 'utf-8  w/ BOM decoded with utf-8-sig %r' % e8s.decode('utf-8-sig')
print 'utf-16 w/ BOM decoded with utf-16    %r' % e16.decode('utf-16')
print 'utf-16 w/ BOM decoded with utf-16le  %r' % e16.decode('utf-16le')

Perhatikan bahwa EF BB BFBOM yang dikodekan UTF-8. Ini tidak diperlukan untuk UTF-8, tetapi hanya berfungsi sebagai tanda tangan (biasanya pada Windows).

Keluaran:

utf-8     'ABC'
utf-8-sig '\xef\xbb\xbfABC'
utf-16    '\xff\xfeA\x00B\x00C\x00'    # Adds BOM and encodes using native processor endian-ness.
utf-16le  'A\x00B\x00C\x00'
utf-16be  '\x00A\x00B\x00C'

utf-8  w/ BOM decoded with utf-8     u'\ufeffABC'    # doesn't remove BOM if present.
utf-8  w/ BOM decoded with utf-8-sig u'ABC'          # removes BOM if present.
utf-16 w/ BOM decoded with utf-16    u'ABC'          # *requires* BOM to be present.
utf-16 w/ BOM decoded with utf-16le  u'\ufeffABC'    # doesn't remove BOM if present.

Perhatikan bahwa utf-16codec membutuhkan BOM untuk hadir, atau Python tidak akan tahu apakah datanya besar atau kecil.

Mark Tolonen
sumber
200

Saya mengalami ini di Python 3 dan menemukan pertanyaan ini (dan solusi ). Saat membuka file, Python 3 mendukung kata kunci pengodean untuk secara otomatis menangani pengodean.

Tanpa itu, BOM dimasukkan dalam hasil baca:

>>> f = open('file', mode='r')
>>> f.read()
'\ufefftest'

Memberikan pengkodean yang benar, BOM dihilangkan dalam hasil:

>>> f = open('file', mode='r', encoding='utf-8-sig')
>>> f.read()
'test'

Hanya 2 sen saya.

siebz0r
sumber
13
Terima kasih, ini adalah solusi aktual dan harus menjadi jawaban yang diterima. Meskipun ini adalah wawasan yang bagus tentang mengapa senar ada di sana, sebagian besar orang yang datang ke sini mencari solusi langsung dan ini dia.
neurino
3
Punya masalah yang sama dengan csv DictReader membaca file csv yang disimpan dari Excel.
LAntz
1
Ya, Excel (bahkan "csv" yang dihasilkan oleh Excel) benar-benar berantakan.
osprey
4

Karakter itu adalah BOM atau "Byte Order Mark". Biasanya diterima sebagai beberapa byte pertama dari suatu file, memberi tahu Anda bagaimana menafsirkan encoding dari sisa data. Anda cukup menghapus karakter untuk melanjutkan. Meskipun, karena kesalahan mengatakan Anda mencoba mengonversi ke 'ascii', Anda mungkin harus memilih penyandian lain untuk apa pun yang Anda coba lakukan.

swstephe
sumber
4

Konten yang Anda garuk dikodekan dalam bentuk unicode daripada teks ascii, dan Anda mendapatkan karakter yang tidak dikonversi ke ascii. 'Terjemahan' yang tepat tergantung pada apa yang dipikirkan oleh halaman web asli. Halaman unicode Python memberikan latar belakang tentang cara kerjanya.

Apakah Anda mencoba mencetak hasilnya atau menempelkannya dalam file? Kesalahan menunjukkan bahwa itu menulis data yang menyebabkan masalah, bukan membacanya. Pertanyaan ini adalah tempat yang baik untuk mencari perbaikannya.

theodox
sumber
0

Berikut ini berdasarkan jawaban dari Mark Tolonen. String menyertakan berbagai bahasa dari kata 'test' yang dipisahkan oleh '|', sehingga Anda dapat melihat perbedaannya.

u = u'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
e8 = u.encode('utf-8')        # encode without BOM
e8s = u.encode('utf-8-sig')   # encode with BOM
e16 = u.encode('utf-16')      # encode with BOM
e16le = u.encode('utf-16le')  # encode without BOM
e16be = u.encode('utf-16be')  # encode without BOM
print('utf-8     %r' % e8)
print('utf-8-sig %r' % e8s)
print('utf-16    %r' % e16)
print('utf-16le  %r' % e16le)
print('utf-16be  %r' % e16be)
print()
print('utf-8  w/ BOM decoded with utf-8     %r' % e8s.decode('utf-8'))
print('utf-8  w/ BOM decoded with utf-8-sig %r' % e8s.decode('utf-8-sig'))
print('utf-16 w/ BOM decoded with utf-16    %r' % e16.decode('utf-16'))
print('utf-16 w/ BOM decoded with utf-16le  %r' % e16.decode('utf-16le'))

Berikut ini adalah uji coba:

>>> u = u'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> e8 = u.encode('utf-8')        # encode without BOM
>>> e8s = u.encode('utf-8-sig')   # encode with BOM
>>> e16 = u.encode('utf-16')      # encode with BOM
>>> e16le = u.encode('utf-16le')  # encode without BOM
>>> e16be = u.encode('utf-16be')  # encode without BOM
>>> print('utf-8     %r' % e8)
utf-8     b'ABCtest\xce\xb2\xe8\xb2\x9d\xe5\xa1\x94\xec\x9c\x84m\xc3\xa1sb\xc3\xaata|test|\xd8\xa7\xd8\xae\xd8\xaa\xd8\xa8\xd8\xa7\xd8\xb1|\xe6\xb5\x8b\xe8\xaf\x95|\xe6\xb8\xac\xe8\xa9\xa6|\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88|\xe0\xa4\xaa\xe0\xa4\xb0\xe0\xa5\x80\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb7\xe0\xa4\xbe|\xe0\xb4\xaa\xe0\xb4\xb0\xe0\xb4\xbf\xe0\xb4\xb6\xe0\xb5\x8b\xe0\xb4\xa7\xe0\xb4\xa8|\xd7\xa4\xd6\xbc\xd7\xa8\xd7\x95\xd7\x91\xd7\x99\xd7\xa8\xd7\x9f|ki\xe1\xbb\x83m tra|\xc3\x96l\xc3\xa7ek|'
>>> print('utf-8-sig %r' % e8s)
utf-8-sig b'\xef\xbb\xbfABCtest\xce\xb2\xe8\xb2\x9d\xe5\xa1\x94\xec\x9c\x84m\xc3\xa1sb\xc3\xaata|test|\xd8\xa7\xd8\xae\xd8\xaa\xd8\xa8\xd8\xa7\xd8\xb1|\xe6\xb5\x8b\xe8\xaf\x95|\xe6\xb8\xac\xe8\xa9\xa6|\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88|\xe0\xa4\xaa\xe0\xa4\xb0\xe0\xa5\x80\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb7\xe0\xa4\xbe|\xe0\xb4\xaa\xe0\xb4\xb0\xe0\xb4\xbf\xe0\xb4\xb6\xe0\xb5\x8b\xe0\xb4\xa7\xe0\xb4\xa8|\xd7\xa4\xd6\xbc\xd7\xa8\xd7\x95\xd7\x91\xd7\x99\xd7\xa8\xd7\x9f|ki\xe1\xbb\x83m tra|\xc3\x96l\xc3\xa7ek|'
>>> print('utf-16    %r' % e16)
utf-16    b"\xff\xfeA\x00B\x00C\x00t\x00e\x00s\x00t\x00\xb2\x03\x9d\x8cTX\x04\xc7m\x00\xe1\x00s\x00b\x00\xea\x00t\x00a\x00|\x00t\x00e\x00s\x00t\x00|\x00'\x06.\x06*\x06(\x06'\x061\x06|\x00Km\xd5\x8b|\x00,nf\x8a|\x00\xc60\xb90\xc80|\x00*\t0\t@\t\x15\tM\t7\t>\t|\x00*\r0\r?\r6\rK\r'\r(\r|\x00\xe4\x05\xbc\x05\xe8\x05\xd5\x05\xd1\x05\xd9\x05\xe8\x05\xdf\x05|\x00k\x00i\x00\xc3\x1em\x00 \x00t\x00r\x00a\x00|\x00\xd6\x00l\x00\xe7\x00e\x00k\x00|\x00"
>>> print('utf-16le  %r' % e16le)
utf-16le  b"A\x00B\x00C\x00t\x00e\x00s\x00t\x00\xb2\x03\x9d\x8cTX\x04\xc7m\x00\xe1\x00s\x00b\x00\xea\x00t\x00a\x00|\x00t\x00e\x00s\x00t\x00|\x00'\x06.\x06*\x06(\x06'\x061\x06|\x00Km\xd5\x8b|\x00,nf\x8a|\x00\xc60\xb90\xc80|\x00*\t0\t@\t\x15\tM\t7\t>\t|\x00*\r0\r?\r6\rK\r'\r(\r|\x00\xe4\x05\xbc\x05\xe8\x05\xd5\x05\xd1\x05\xd9\x05\xe8\x05\xdf\x05|\x00k\x00i\x00\xc3\x1em\x00 \x00t\x00r\x00a\x00|\x00\xd6\x00l\x00\xe7\x00e\x00k\x00|\x00"
>>> print('utf-16be  %r' % e16be)
utf-16be  b"\x00A\x00B\x00C\x00t\x00e\x00s\x00t\x03\xb2\x8c\x9dXT\xc7\x04\x00m\x00\xe1\x00s\x00b\x00\xea\x00t\x00a\x00|\x00t\x00e\x00s\x00t\x00|\x06'\x06.\x06*\x06(\x06'\x061\x00|mK\x8b\xd5\x00|n,\x8af\x00|0\xc60\xb90\xc8\x00|\t*\t0\t@\t\x15\tM\t7\t>\x00|\r*\r0\r?\r6\rK\r'\r(\x00|\x05\xe4\x05\xbc\x05\xe8\x05\xd5\x05\xd1\x05\xd9\x05\xe8\x05\xdf\x00|\x00k\x00i\x1e\xc3\x00m\x00 \x00t\x00r\x00a\x00|\x00\xd6\x00l\x00\xe7\x00e\x00k\x00|"
>>> print()

>>> print('utf-8  w/ BOM decoded with utf-8     %r' % e8s.decode('utf-8'))
utf-8  w/ BOM decoded with utf-8     '\ufeffABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> print('utf-8  w/ BOM decoded with utf-8-sig %r' % e8s.decode('utf-8-sig'))
utf-8  w/ BOM decoded with utf-8-sig 'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> print('utf-16 w/ BOM decoded with utf-16    %r' % e16.decode('utf-16'))
utf-16 w/ BOM decoded with utf-16    'ABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'
>>> print('utf-16 w/ BOM decoded with utf-16le  %r' % e16.decode('utf-16le'))
utf-16 w/ BOM decoded with utf-16le  '\ufeffABCtestβ貝塔위másbêta|test|اختبار|测试|測試|テスト|परीक्षा|പരിശോധന|פּרובירן|kiểm tra|Ölçek|'

Perlu diketahui bahwa hanya keduanya utf-8-sigdan utf-16mendapatkan kembali string asli setelah keduanya encodedan decode.

caot
sumber
-3

Masalah ini pada dasarnya muncul ketika Anda menyimpan kode python Anda dalam pengkodean UTF-8 atau UTF-16 karena python menambahkan beberapa karakter khusus di awal kode secara otomatis (yang tidak diperlihatkan oleh editor teks) untuk mengidentifikasi format pengkodean. Tetapi, ketika Anda mencoba mengeksekusi kode itu memberi Anda kesalahan sintaks pada baris 1 yaitu, mulai kode karena kompiler python memahami pengkodean ASCII . ketika Anda melihat kode file menggunakan fungsi read () Anda dapat melihat di awal kode yang dikembalikan '\ ufeff' ditampilkan. Satu solusi paling sederhana untuk masalah ini adalah hanya dengan mengubah pengkodean kembali ke pengkodean ASCII(untuk ini Anda dapat menyalin kode Anda ke notepad dan menyimpannya Ingat! pilih pengkodean ASCII ... Semoga ini bisa membantu.

Jagdish Chauhan
sumber