2012-11-06 11 views
6

Mesajda bir unicode içeren python 2.7.x dosyasında istisna oluşturmaya çalışıyorum. İşe yaramış gibi görünmüyorum.python 2'de ingilizce olmayan karakterler içeren istisnayı yükseltmek mümkün mü?

Hata msg dosyasında unicode eklenmesi desteklenmiyor mu veya önerilmez Veya sys.stderr'a bakmak zorunda mıyım?

# -*- coding: utf-8 -*- 
class MyException(Exception): 
    def __init__(self, value): 
    self.value = value 
    def __str__(self): 
    return self.value 
    def __repr__(self): 
    return self.value 
    def __unicode__(self): 
    return self.value 

desc = u'something bad with field \u4443' 

try: 
    raise MyException(desc) 
except MyException as e: 
    print(u'Inside try block : ' + unicode(e)) 

# here is what i wish to make work 
raise MyException(desc) 

Çalıştırma komut dosyası aşağıdaki çıktıyı üretir. Denememde/dizimde dizeyi problemsiz yazdırabilirim.

Sorunum, try/except dışında.

Inside try block : something bad with field 䑃 
Traceback (most recent call last): 
    File "C:\Python27\lib\bdb.py", line 387, in run 
    exec cmd in globals, locals 
    File "C:\Users\ghis3080\r.py", line 25, in <module> 
    raise MyException(desc) 
MyException: something bad with field \u4443 

Şimdiden teşekkürler.

cevap

1

Bu davranış Python sürümüne ve çevreye göre değişir. Python 3 günü sys.stderr için karakter kodlama hatası işleyicisi daima 'backslashreplace' geçerli:

from __future__ import unicode_literals, print_function 
import sys 

s = 'unicode "\u2323" smile' 
print(s) 
print(s, file=sys.stderr) 
try: 
    raise RuntimeError(s) 
except Exception as e: 
    print(e.args[0]) 
    print(e.args[0], file=sys.stderr) 
    raise 

python3:

$ PYTHONIOENCODING=ascii:ignore python3 raise_unicode.py 
unicode "" smile 
unicode "\u2323" smile 
unicode "" smile 
unicode "\u2323" smile 
Traceback (most recent call last): 
    File "raise_unicode.py", line 8, in <module> 
    raise RuntimeError(s) 
RuntimeError: unicode "\u2323" smile 

python2:

sistemimde ise
$ PYTHONIOENCODING=ascii:ignore python2 raise_unicode.py 
unicode "" smile 
unicode "" smile 
unicode "" smile 
unicode "" smile 
Traceback (most recent call last): 
    File "raise_unicode.py", line 8, in <module> 
    raise RuntimeError(s) 
RuntimeError 

hata mesajı yenen python2.

Not: Windows üzerinde deneyebilirsin:

T:\> set PYTHONIOENCODING=ascii:ignore 
T:\> python raise_unicode.py 

Karşılaştırma için: Benim durumumda

$ python3 raise_unicode.py 
unicode "⌣" smile 
unicode "⌣" smile 
unicode "⌣" smile 
unicode "⌣" smile 
Traceback (most recent call last): 
    File "raise_unicode.py", line 8, in <module> 
    raise RuntimeError(s) 
RuntimeError: unicode "⌣" smile 
2

Python bu şekilde çalışır. Gördüğünüzün Python çekirdek kütüphanesinde traceback._some_string()'dan geldiğini düşünüyorum. Bu modülde, bir yığın izi tamamlandığında, bu yöntemdeki kod ilk olarak str() kullanarak iletiyi dönüştürmeyi dener, ardından bu bir özel durum oluşturursa, iletiyi unicode() kullanarak dönüştürür, sonra encode("ascii", "backslashreplace") kullanarak ascii'ye dönüştürür. Geçerli çıktı alıyorsunuz ve her şey düzgün çalışıyor, benim tahminim Python'un hata mesajını dönüştürmek için en iyisini yapmasıdır, böylece platformu yürüten herhangi bir sorun olmadan sorunsuz bir şekilde görüntülenecektir. Bu sadece karakterinizin unicode kod noktasıdır. Bu dönüşüm, try/except bloğunuzda gerçekleşmez; çünkü bu dönüştürme, yığın izleri üreten mekanizmaya özgü bir şeydir (yakalanmamış istisnalar durumunda olduğu gibi).

1

senin örneğin gerektiği gibi çalıştı, güzel Unicode baskı.

Ancak bazen istisna yığınıyla (veya çıkış/geri eğik çizgi ile) unicode karakterleri yazdırılmış halde çok fazla sorunla karşılaşırsınız. Engelin üstesinden gelmek ve normal mesajları yazdırmak mümkündür.

Çıktıyla ilgili sorun örneği (Python 2.7, Linux):

~/.../sources/C_patch$ python SO.py 
Traceback (most recent call last): 
    File "SO.py", line 25, in <module> 
    raise SyntaxError(desc) 
SyntaxError 

aslında değişmeden unicode görmek için, ham bayt kodlamak ve istisna nesnesine besleyebilir:

# -*- coding: utf-8 -*- 
desc = u'something bad with field ¾' 
raise SyntaxError(desc.encode('utf-8', 'replace')) 

Sadece kesik veya vidalı mesajı yazdırılır

~/.../sources/C_patch$ python SO.py 
Traceback (most recent call last): 
    File "SO.py", line 3, in <module> 
    raise SyntaxError(desc.encode('utf-8', 'replace')) 
SyntaxError: something bad with field ¾ 
:
# -*- coding: utf-8 -*- 
desc = u'something bad with field ¾' 
raise SyntaxError(desc.encode('utf-8', 'replace')) 

Bu sefer tam mesajı göreceksiniz 0

İsterseniz yapıcınıza value.encode('utf-8', 'replace') yapabilirsiniz, ancak sistem istisnası ile örnekte olduğu gibi raise ifadesinde bunu yapmanız gerekecektir.

Buradaki ipucu buradan alınır: Overcoming frustration: Correctly using unicode in python2 (birçok yardımcıyla büyük bir kütüphane vardır ve bunların tümü yukarıdaki örnekte yerlerinden çıkarılabilir).

+0

.encode ('utf-8') gerçekten bana yardımcı oldu, ikinci parametreyi bile kullanmadım. –

İlgili konular