2010-10-04 38 views
8

Tôi muốn hàm của tôi lấy một đối số có thể là đối tượng unicode hoặc chuỗi được mã hóa utf-8. Bên trong hàm của tôi, tôi muốn chuyển đối số thành unicode. Tôi có một cái gì đó như thế này:Giải mã nếu nó không phải là unicode

def myfunction(text): 
    if not isinstance(text, unicode): 
     text = unicode(text, 'utf-8') 

    ... 

Có thể tránh việc sử dụng isinstance không? Tôi đang tìm kiếm thứ gì đó thân thiện với vịt hơn.

Trong khi thử nghiệm của tôi với giải mã, tôi đã chạy vào một số hành vi kỳ lạ của Python. Ví dụ:

>>> u'hello'.decode('utf-8') 
u'hello' 
>>> u'cer\xf3n'.decode('utf-8') 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in po 
sition 3: ordinal not in range(128) 

Hoặc

>>> u'hello'.decode('utf-8') 
u'hello' 12:11 
>>> unicode(u'hello', 'utf-8') 
Traceback (most recent call last): 
File "<input>", line 1, in <module> 
TypeError: decoding Unicode is not supported 

Bằng cách này. Tôi đang sử dụng Python 2.6

+0

Bạn có thể muốn xem xét câu hỏi này: [Python UnicodeDecodeError - Tôi hiểu nhầm Unicode?] (Http://stackoverflow.com/questions/368805/) – tzot

Trả lời

14

Bạn chỉ có thể thử giải mã bằng codec 'utf-8' và nếu điều đó không hoạt động, hãy trả lại đối tượng.

def myfunction(text): 
    try: 
     text = unicode(text, 'utf-8') 
    except TypeError: 
     return text 

print(myfunction(u'cer\xf3n')) 
# cerón 

Khi bạn chụp đối tượng unicode và gọi phương thức decode của nó với 'utf-8' codec, Python đầu tiên cố gắng để chuyển đổi đối tượng unicode đến một đối tượng chuỗi, và sau đó nó gọi decode đối tượng chuỗi của ('utf-8') phương pháp.

Đôi khi chuyển đổi từ đối tượng unicode thành đối tượng chuỗi không thành công vì Python2 sử dụng codec ascii theo mặc định.

Vì vậy, nói chung, không bao giờ cố gắng giải mã các đối tượng unicode. Hoặc, nếu bạn phải cố gắng, bẫy nó trong một khối try..except. Có thể có một vài codec giải mã các đối tượng unicode hoạt động trong Python2 (xem bên dưới), nhưng chúng đã bị loại bỏ trong Python3.

Xem Python bug ticket này cho một cuộc thảo luận thú vị về vấn đề, và cũng Guido van Rossum's blog:

"Chúng tôi đang áp dụng một cách tiếp cận hơi khác nhau đến codec: while bằng Python 2, codec có thể chấp nhận hoặc Unicode hoặc 8-bit làm đầu vào và xuất ra dưới dạng đầu ra , trong Py3k, mã hóa luôn là một bản dịch từ một chuỗi Unicode (văn bản) thành một mảng byte và giải mã luôn đi ngược lại hướng. Điều này có nghĩa là chúng tôi phải thả một vài codec không vừa với mô hình này, ví dụ: rot13, base64 và bz2 (các chuyển đổi đó vẫn được hỗ trợ , không thông qua API mã hóa/giải mã ). "

0

Tôi không biết bất kỳ cách nào tốt để tránh việc kiểm tra chức năng của bạn, nhưng có thể một người khác sẽ hoạt động. Tôi có thể chỉ ra rằng hai điều kỳ quặc mà bạn trích dẫn là bởi vì bạn đang làm điều gì đó không có ý nghĩa: Cố gắng giải mã thành Unicode cái gì đó đã được giải mã thành Unicode.

Đầu tiên thay vì sẽ trông như thế này, mà giải mã mã hóa UTF-8 của chuỗi đó vào phiên bản Unicode:

>>> 'cer\xc3\xb3n'.decode('utf-8') 
u'cer\xf3n' 

Và thứ hai của bạn sẽ giống như thế này (không sử dụng một chuỗi u'' Unicode đen) :

>>> unicode('hello', 'utf-8') 
u'hello' 
+0

Điều kỳ lạ là đối tượng unicode có Thậm chí weirder là phương thức hoạt động đôi khi và đôi khi không giống nhau cho các cuộc gọi unicode() –

+0

Vâng, chắc chắn có một số điểm kỳ lạ đối với API, vì một lệnh gọi đến 'unicode' với một chuỗi Unicode và n o mã hóa được chỉ định sẽ luôn hoạt động trong khi cuộc gọi với bất kỳ mã hóa nào được chỉ định sẽ luôn thất bại. –

Các vấn đề liên quan