2012-11-06 6 views
6

Sto cercando di generare un'eccezione in python 2.7.x che include un unicode nel messaggio. Non riesco a farlo funzionare.possibile generare un'eccezione che includa caratteri non inglesi in python 2?

Non è supportato o non è consigliabile includere unicode nel messaggio di errore? O devo guardare sys.stderr?

# -*- 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) 

Lo script in esecuzione produce l'output di seguito. All'interno del mio tentativo/eccetto che posso stampare la stringa senza problemi.

Il mio problema è al di fuori del tentativo/eccetto.

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 

Grazie in anticipo.

risposta

1

Il comportamento dipende dalla versione di Python e dall'ambiente. Sul Python 3 il gestore degli errori di codifica dei caratteri per sys.stderr è sempre 'backslashreplace':

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:

$ 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 

Questo è il mio sistema il messaggio di errore si mangia su python2.

Nota: su Windows si potrebbe provare:

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

Per fare un confronto:

$ 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

Ecco come funziona Python. Credo che quello che state vedendo provenga da traceback._some_string() nella libreria principale di Python. In quel modulo, quando viene eseguita una traccia stack, il codice in quel metodo tenta prima di convertire il messaggio utilizzando str(), quindi se genera un'eccezione, converte il messaggio utilizzando unicode(), quindi lo converte in ascii utilizzando encode("ascii", "backslashreplace"). Stai ottenendo un output valido e tutto funziona correttamente, suppongo che Python stia facendo del suo meglio per pseudo-down convertire il messaggio di errore in modo che venga visualizzato senza problemi, indipendentemente dalla piattaforma che lo esegue. Questo è solo il codice unicode per il tuo personaggio. Non si verifica nel blocco try/except perché questa conversione è qualcosa di specifico del meccanismo che produce tracce di stack (come nel caso di eccezioni non rilevate).

1

Nel mio caso tuo esempio ha funzionato come dovrebbe, la stampa bella unicode.

Ma a volte si verificano molti problemi con lo stack di eccezioni stampato senza (o con caratteri unicode con escape/backslash). È possibile superare l'ostacolo e stampare i messaggi normali.

Esempio del problema con l'output (Python 2.7, Linux):

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

verrà stampata messaggio solo troncato o avvitata:

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

Per vedere effettivamente l'unicode inalterata, è possibile codificare a byte prime e mangimi in oggetto eccezione:

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

Questa volta si vedrà il messaggio completo:

~/.../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 ¾ 

È possibile eseguire value.encode('utf-8', 'replace') nel costruttore, se lo si desidera, ma con l'eccezione di sistema sarà necessario farlo nell'istruzione raise, come nell'esempio.

Il suggerimento è preso da qui: Overcoming frustration: Correctly using unicode in python2 (ci sono grandi librerie con molti helper e tutti possono essere ridotti nell'esempio precedente).

+0

.encode ('utf-8') mi ha davvero aiutato, non ho nemmeno dovuto usare il secondo parametro. –

Problemi correlati