u '\ ufeff' trong chuỗi Python


152

Tôi nhận được một lỗi với các patter sau:

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

Không chắc chắn những gì u'\ufeff', nó xuất hiện khi tôi đang quét web. Làm thế nào tôi có thể khắc phục tình hình? Các .replace()phương pháp chuỗi không hoạt động trên nó.


6
Trường hợp đầu vào này đến từ đâu? Bạn đang cố gắng làm gì? Vui lòng bao gồm mã Python của bạn.

7
Tình cờ, tôi thấy rằng .replace () hoạt động trong trăn hiện đại nếu tôi nhớ chỉ báo unicode: s.replace (u '\ ufeff', '')
Doug Bradshaw

@DougBradshaw khi bạn nói "trăn hiện đại", ý bạn là, 2.7+ hay 3.0+?
teewuane

Điểm tốt. Ý nghĩa, 2.7+.
Doug Bradshaw

Câu trả lời:


184

Ký tự Unicode U+FEFFlà dấu thứ tự byte hoặc BOM và được sử dụng để cho biết sự khác biệt giữa mã hóa UTF-16 lớn và nhỏ. Nếu bạn giải mã trang web bằng cách sử dụng codec phù hợp, Python sẽ xóa nó cho bạn. Ví dụ:

#!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')

Lưu ý rằng đó EF BB BFlà BOM được mã hóa UTF-8. UTF-8 không bắt buộc, nhưng chỉ dùng làm chữ ký (thường là trên Windows).

Đầu ra:

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.

Lưu ý rằng utf-16codec yêu cầu phải có BOM hoặc Python sẽ không biết liệu dữ liệu là lớn hay nhỏ.


200

Tôi đã gặp vấn đề này trên Python 3 và tìm thấy câu hỏi này (và giải pháp ). Khi mở tệp, Python 3 hỗ trợ từ khóa mã hóa để tự động xử lý mã hóa.

Không có nó, BOM được bao gồm trong kết quả đọc:

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

Đưa ra mã hóa chính xác, BOM bị bỏ qua trong kết quả:

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

Chỉ cần 2 xu của tôi.


13
Cảm ơn bạn, đây là giải pháp thực tế và nên là câu trả lời được chấp nhận. Trong khi đây là cái nhìn sâu sắc về lý do tại sao chuỗi ở đó, hầu hết những người đến đây đang tìm kiếm một giải pháp đơn giản và đây là nó.
neurino

3
Có vấn đề tương tự với DictReader csv khi đọc tệp csv được lưu từ Excel.
LArntz

1
Có, Excel (thậm chí "csv" do Excel tạo) thực sự là một mớ hỗn độn.
osprey

4

Nhân vật đó là BOM hoặc "Byte Order Mark". Nó thường được nhận dưới dạng một vài byte đầu tiên của tệp, cho bạn biết cách diễn giải mã hóa phần còn lại của dữ liệu. Bạn có thể chỉ cần loại bỏ các nhân vật để tiếp tục. Mặc dù, vì lỗi nói rằng bạn đang cố chuyển đổi thành 'ascii', có lẽ bạn nên chọn một mã hóa khác cho bất cứ điều gì bạn đang cố gắng làm.


4

Nội dung bạn đang quét được mã hóa thành unicode chứ không phải là văn bản ascii và bạn sẽ nhận được một ký tự không chuyển đổi thành ascii. Quyền "dịch" phụ thuộc vào trang web ban đầu nghĩ gì. Trang unicode của Python cung cấp nền tảng về cách thức hoạt động của nó.

Bạn đang cố gắng để in kết quả hoặc dán nó trong một tập tin? Lỗi cho thấy nó ghi dữ liệu gây ra sự cố, không đọc nó. Câu hỏi này là một nơi tốt để tìm kiếm các bản sửa lỗi.


0

Dưới đây là dựa trên câu trả lời từ Mark Tolonen. Chuỗi bao gồm các ngôn ngữ khác nhau của từ 'kiểm tra' được phân tách bằng '|', do đó bạn có thể thấy sự khác biệt.

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'))

Đây là một lần chạy thử:

>>> 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|'

Thật đáng để biết rằng chỉ có cả hai utf-8-sigutf-16lấy lại chuỗi gốc sau cả hai encodedecode.


-3

Vấn đề này cơ bản phát sinh khi bạn lưu mã python của mình trong mã hóa UTF-8 hoặc UTF-16 vì python tự động thêm một số ký tự đặc biệt vào đầu mã (không được trình soạn thảo văn bản hiển thị) để xác định định dạng mã hóa. Nhưng, khi bạn cố gắng thực thi mã, nó sẽ cung cấp cho bạn lỗi cú pháp trong dòng 1 tức là bắt đầu mã vì trình biên dịch python hiểu mã hóa ASCII . khi bạn xem mã của tệp bằng hàm read (), bạn có thể thấy ở đầu mã trả về '\ ufeff' được hiển thị. Giải pháp đơn giản nhất cho vấn đề này chỉ là thay đổi mã hóa trở lại mã hóa ASCII(để làm điều này, bạn có thể sao chép mã của mình vào một notepad và lưu nó Hãy nhớ! chọn mã hóa ASCII ... Hy vọng điều này sẽ giúp ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.