2011-11-22 22 views
7

Về cơ bản tôi chỉ muốn có thể tạo các cá thể bằng cách sử dụng một lớp có tên là Chai: ví dụ class Bottle(object):... và sau đó trong một mô-đun khác có thể chỉ đơn giản là "in" bất kỳ trường hợp mà không cần phải hack mã để gọi một cách rõ ràng mã hóa ký tự thường trình.Python: Cách ép "in" để sử dụng __unicode__ thay vì __str__, hoặc nếu không tự nhiên "in" tin nhắn mà không gọi một cách rõ ràng unicode()

Nói tóm lại, khi tôi cố gắng:

obj=Bottle(u"味精") 
print obj 

Hoặc để một "tại chỗ" "print":

print Bottle(u"味精") 

tôi nhận được:

"UnicodeEncodeError: 'ascii' codec can't encode characters" 

câu hỏi stackoverflow tương tự:

¢ Hiện không khả thi để chuyển sang python3. ¢

Giải pháp hoặc gợi ý (và giải thích) về cách thực hiện in utf-8 tại chỗ (giống như lớp U không thành công bên dưới) sẽ được đánh giá cao. :-)

thanx N

-

đang

mẫu:

-------- 8> < - - - - cắt ở đây - - - -

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

def setdefaultencoding(encoding="utf-8"): 
    import sys, codecs 

    org_encoding = sys.getdefaultencoding() 
    if org_encoding == "ascii": # not good enough 
    print "encoding set to "+encoding 
    sys.stdout = codecs.getwriter(encoding)(sys.stdout) 
    sys.stderr = codecs.getwriter(encoding)(sys.stderr) 

setdefaultencoding() 

msg=u"味精" # the message! 

class U(unicode): pass 

m1=U(msg) 

print "A)", m1 # works fine, even with unicode, but 

class Bottle(object): 
    def __init__(self,msg): self.msg=msg 
    def __repr__(self): 
    print "debug: __repr__",self.msg 
    return '{{{'+self.msg+'}}}' 
    def __unicode__(self): 
    print "debug: __unicode__",self.msg 
    return '{{{'+self.msg+'}}}' 
    def __str__(self): 
    print "debug: __str__",self.msg 
    return '{{{'+self.msg+'}}}' 
    def decode(self,arg): print "debug: decode",self.msg 
    def encode(self,arg): print "debug: encode",self.msg 
    def translate(self,arg): print "debug: translate",self.msg 

m2=Bottle(msg) 

#print "B)", str(m2) 
print "C) repr(x):", repr(m2) 
print "D) unicode(x):", unicode(m2) 
print "E)",m2 # gives: UnicodeEncodeError: 'ascii' codec can't encode characters 

-------- 8> < - - - - cắt ở đây - - - - Python 2.4 đầu ra:

encoding set to utf-8 
A) 味精 
C) repr(x): debug: __repr__ 味精 
{{{\u5473\u7cbe}}} 
D) unicode(x): debug: __unicode__ 味精 
{{{味精}}} 
E) debug: __str__ 味精 
Traceback (most recent call last): 
    File "./uc.py", line 43, in ? 
    print "E)",m2 # gives: UnicodeEncodeError: 'ascii' codec can't encode characters 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-4: ordinal not in range(128) 

-------- 8> < - - - - cắt ở đây - - - - Python 2.6 đầu ra:

encoding set to utf-8 
A) 味精 
C) repr(x): debug: __repr__ 味精 
Traceback (most recent call last): 
    File "./uc.py", line 41, in <module> 
    print "C) repr(x):", repr(m2) 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 3-4: ordinal not in range(128) 
+0

đầu ra không phản ánh mã, ví dụ: 'repr (x)' sẽ tạo 'UnicodeEncodeError' quá – jfs

+0

@ J.F. Sebastian: Python 2.4 sản xuất ở trên, vì vậy tôi chạy mã trên 2.6 và repr bây giờ cũng tạo ra thông báo lỗi. – NevilleDNZ

+0

Thông báo "UnicodeEncodeError: 'ascii' codec không thể mã hóa các ký tự" khiến tôi nghi ngờ rằng "in" không sử dụng "sys.stdout" vì tôi đã thay đổi codec/mã hóa của tệp này thành "utf-8" với "sys.stdout = codecs.getwriter (encoding) (sys.stdout) " – NevilleDNZ

Trả lời

6

nếu bạn sử dụng sys.stdout = codecs.getwriter(encoding)(sys.stdout) thì bạn nên vượt qua chuỗi Unicode để print :

>>> print u"%s" % Bottle(u"魯賓遜漂流記") 
debug: __unicode__ 魯賓遜漂流記 
{{{魯賓遜漂流記}}} 

như @ bobince chỉ ra trong các ý kiến: tránh thay đổi sys.stdout theo cách đó nếu không nó có thể phá vỡ bất kỳ mã thư viện làm việc với sys.stdout và không mong đợi để in chuỗi Unicode.

Nói chung:

__unicode__() nên trả lại chuỗi Unicode:

def __init__(self, msg, encoding='utf-8'): 
    if not isinstance(msg, unicode): 
     msg = msg.decode(encoding) 
    self.msg = msg 

def __unicode__(self): 
    return u"{{{%s}}}" % self.msg 

__repr__() nên trở ascii-thân thiện str đối tượng:

def __repr__(self): 
    return "Bottle(%r)" % self.msg 

__str__() nên trở str đối tượng. Thêm tùy chọnencoding để ghi lại mã hóa nào được sử dụng. Không có cách nào tốt để lựa chọn mã hóa ở đây:

def __str__(self, encoding="utf-8") 
    return self.__unicode__().encode(encoding) 

Xác định write() phương pháp:

def write(self, file, encoding=None): 
    encoding = encoding or getattr(file, 'encoding', None) 
    s = unicode(self) 
    if encoding is not None: 
     s = s.encode(encoding) 
    return file.write(s) 

Nó phải bao gồm các trường hợp khi tập tin có mã hóa riêng của mình hoặc nó hỗ trợ chuỗi Unicode trực tiếp.

+0

@Robinson Crusoe :-) - ThanX cho điều đó! Tôi cũng thấy 'in unicode (Bottle (u" 魯賓遜 漂流 記 ")' hoạt động. Nhưng ** kỳ lạ ** thay thế rõ ràng 'print >> sys.stdout, Bottle (u" 魯賓遜 漂流 記 ")' không hoạt động (ngay cả với mã 'sys.stdout = codecs.getwriter (" utf-8 ") (sys.stdout)' ở trên cùng. – NevilleDNZ

+0

Hãy nhận biết, mã hóa ký tự của thiết bị đầu cuối của bạn cũng là một yếu tố ở đây. câu lệnh 'print' gọi' __str__', tôi tin đây là lỗi trong câu lệnh 'print'. – wberry

+1

Hãy hack rất cẩn thận' sys.stdout' thành luồng ký tự thay vì luồng byte. Bất kỳ mã thư viện nào bạn đang sử dụng để cố gắng viết các byte không phải ASCII vào 'sys.stdout' bây giờ sẽ thất bại. Và nếu chúng ta đang nói về việc xuất ra Windows Command Prompt, bạn chỉ nên từ bỏ bây giờ, bạn sẽ không nhận được Unicode ra khỏi nó bằng cách sử dụng thư viện chuẩn C stdio Python (và hầu hết các ngôn ngữ khác) sử dụng – bobince

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