2013-11-04 11 views
7

Sto tentando di rimuovere tutti i caratteri non ascii da un documento di testo. Ho trovato un pacchetto che dovrebbe fare proprio questo, https://pypi.python.org/pypi/UnidecodeCome utilizzare unidecode in python (3.3)

Dovrebbe accettare una stringa e convertire tutti i caratteri non ascii nel carattere ASCII più vicino disponibile. Ho usato questo stesso modulo in perl abbastanza facilmente semplicemente chiamando while (<input>) { $_ = unidecode($_); } e questo è una porta diretta del modulo perl, la documentazione indica che dovrebbe funzionare allo stesso modo.

Sono sicuro che questo è qualcosa di semplice, non capisco abbastanza di codifica di caratteri e file per sapere qual è il problema. Il mio origfile è codificato in UTF-8 (convertito da UCS-2LE). Il problema potrebbe avere più a che fare con la mia mancanza di conoscenza della codifica e la gestione di stringhe sbagliate rispetto al modulo, si spera che qualcuno possa spiegare il perché. Ho provato tutto quello che so senza inserire codice in modo casuale e cercare gli errori che sto ottenendo senza fortuna fino ad ora.

Ecco il mio pitone

from unidecode import unidecode 

def toascii(): 
    origfile = open(r'C:\log.convert', 'rb') 
    convertfile = open(r'C:\log.toascii', 'wb') 

    for line in origfile: 
     line = unidecode(line) 
     convertfile.write(line) 

    origfile.close() 
    convertfile.close() 

toascii(); 

Se non aprire il file originale in modalità byte (origfile = open('file.txt','r') poi ho un errore UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 1563: character maps to <undefined> dalla linea for line in origfile:.

Se lo apro in modalità byte 'rb' ottengo dalla riga line = unidecode(line).

se dichiaro la linea come una stringa line = unidecode(str(line)), quindi scriverà nel file, ma ... non correttamente. \r\n'b'\xef\xbb\xbf[ 2013.10.05 16:18:01 ] User_Name > .\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\ Sta scrivendo i caratteri \ n, \ r, etc e unicode invece di convertirli in qualcosa.

Se converto la linea di stringa come sopra, e aprire il convertfile in modalità byte 'wb' dà l'errore TypeError: 'str' does not support the buffer interface

Se l'apro in modalità byte senza dichiararlo una stringa 'wb' e unidecode(line) poi ho la TypeError: ord() expected string length 1, but int found errore di nuovo.

risposta

8

Il modulo unidecode accetta unicode valori di stringa e restituisce una stringa Unicode in Python 3. Si stanno dando i dati binari invece. Decodifica per unicode o apri il file di testo di input in modalità testo e codifica il risultato in ASCII prima di scriverlo in un file o apri il file di testo di output in modalità testo.

Citando la documentazione del modulo:

The module exports a single function that takes an Unicode object (Python 2.x) or string (Python 3.x) and returns a string (that can be encoded to ASCII bytes in Python 3.x)

enfasi è mia.

Questo dovrebbe funzionare:

def toascii(): 
    with open(r'C:\log.convert', 'r', encoding='utf8') as origfile, open(r'C:\log.toascii', 'w', encoding='ascii') as convertfile: 
     for line in origfile: 
      line = unidecode(line) 
      convertfile.write(line) 

Ciò apre il file di input in modus di testo (utilizzando la codifica UTF-8, che a giudicare dalla tua linea di campione è corretto) e scrive in modus testo (codifica ASCII).

È necessario specificare esplicitamente la codifica del file che si sta aprendo; se si omette la codifica, viene utilizzata la locale corrente del sistema (il risultato di una chiamata locale.getpreferredencoding(False)), che di solito non sarà il codec corretto se il codice deve essere portatile.

+0

Al primo tentativo non sembra funzionare, ottengo gli stessi problemi di quando ho usato str(), cioè finisco con righe come '\ r \ n \ xef \ xbb \ xbf'. Vado a vedere cosa posso fare con quei suggerimenti però. – BeanBagKing

+1

@BeanBagKing: il 'b '\ xef \ xbb \ xbf'' che vedi è una rappresentazione di un valore di byte; ciò significa che stai passando il risultato di 'str (bytevalue)', non un valore di stringa unicode come decodificato dal file di input. –

+0

corretto, in qualche modo il mio file originale è stato sovrascritto con quei valori. Ho ancora errori con il codice che hai dato però, 'UnicodeDecodeError: il codec 'charmap' non può decodificare il byte 0x90 nella posizione 1563: cha racter maps a '. Se apro il file in modalità byte, ottengo la stringa 'attesa di lunghezza 1, ma int trovata 'Potrebbe essere questo un problema più fondamentale con la codifica del mio file originale? – BeanBagKing

Problemi correlati