2010-09-18 5 views
6

Quando provo a stampare una stringa unicode sul mio server dev, funziona correttamente ma il server di produzione solleva un'eccezione.La stampa Python funziona in modo diverso su server diversi

File "/home/user/twistedapp/server.py", line 97, in stringReceived 
    print "sent:" + json 
File "/usr/lib/python2.6/dist-packages/twisted/python/log.py", line 555, in write 
    d = (self.buf + data).split('\n') 
exceptions.UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 28: ordinal not in range(128) 

In realtà è un'applicazione storta e stampa avanti per registrare il file.

repr() di stringhe uguali. Impostazioni locali impostate su en_US.UTF-8.

Sono presenti configurazioni necessarie per verificare che funzionino allo stesso modo su entrambi i server?

+1

Quali versioni di sistema operativo e Python sono in esecuzione i server? – Puddingfox

+0

Ubuntu 10.04 Server sia – Soid

+0

sia Python 2.6.5 – Soid

risposta

1

Unicode non è supportato dagli osservatori di registro incorporati di Twisted. Vedere http://twistedmatrix.com/trac/ticket/989 per i progressi sull'aggiunta di supporto per questo, o per vedere cosa si può fare per dare una mano.

Fino a quando # 989 non viene risolto e la correzione si trova in una versione Twisted su cui è distribuita l'applicazione, non registrare unicode. Registrare solo str.

+0

perché potrebbe funzionare diversamente sui diversi server? – Soid

+0

Sarebbe ok se avrei bisogno di codificare o decodificare o qualcosa del genere. Ma il server di produzione richiede di eseguire la decodifica ('utf8') e il server di sviluppo non consente di farlo. – Soid

7

print ing delle stringhe Unicode si basa su sys.stdout (standard output del processo) con una corretta attributo .encoding che Python può utilizzare per codificare la stringa unicode in una stringa di byte per eseguire la stampa desiderata - e che l'impostazione dipende dal modo il sistema operativo è impostato, in cui viene indirizzato l'output standard e così via.

Se non esiste un attributo di questo tipo, viene utilizzato il codice codificato predefinito ascii e, come si è visto, spesso non fornisce i risultati desiderati ;-).

È possibile controllare getattr(sys.stdout, 'encoding', None) per vedere se la codifica è lì (se lo è, è sufficiente tenere le dita incrociate che è corretto ... o, forse, provare qualche trucco pesantemente specifico per piattaforma da indovinare sul sistema corretto codifica da verificare ;-). Se non lo è, in generale, non esiste un modo affidabile o multipiattaforma per indovinare cosa potrebbe essere. È possibile provare 'utf8', la codifica universale che funziona in molti casi (sicuramente più di ascii fa ;-), ma è davvero un giro della ruota della roulette.

Per maggiore affidabilità, il programma dovrebbe avere il proprio file di configurazione per dirgli quale codifica di uscita utilizzare (magari con 'utf8' come predefinito se non diversamente specificato).

E 'anche meglio, per la portabilità, per svolgere la propria codifica, cioè, non

print someunicode 

ma piuttosto

print someunicode.encode(thecodec) 

e in realtà, se si preferisce avere in uscita incomplete di un incidente,

print someunicode.encode(thecodec, 'ignore') 

(che salta semplicemente n on-codificabili caratteri), o, in genere meglio,

print someunicode.encode(thecodec, 'replace') 

(che utilizza segnaposto punto interrogativo per i caratteri non codificabili).

+2

Penso che valga la pena ricordare che su sistemi UNIX, sys.stdout.la codifica è impostata in base alle variabili di ambiente 'LANG',' LC_ALL' e 'LC_CTYPE', e che è * solo * impostata se sys.stdout è connesso a un terminale. Le stesse stampe di lavoro possono sfortunatamente interrompersi quando si reindirizza l'output su un file o su un altro programma. Ciò rende ancora più importante codificare esplicitamente il tuo unicode. –

+0

@Thomas, sì, assolutamente, punto eccellente! –

+0

Non funziona perché le uscite di stampa vengono registrate. Ho aggiornato la mia domanda. Grazie per la risposta. Locale impostato su en_US.UTF-8 su entrambi i server. – Soid