2013-09-02 11 views
5

So di più sulla riparazione di biciclette, sull'uso della motosega e sulla sicurezza di trincea rispetto a Python o alla codifica del testo; con questo in mente ...Le insidie ​​nel mio codice per rilevare la codifica di file di testo con Python?

codifica del testo Python sembra essere un problema perenne (mia domanda: Searching text files' contents with various encodings with Python?, e altri che ho letto:. 1, 2 ho preso una crepa a scrivere del codice da indovinare la codifica di seguito.

Nei test limitato questo codice sembra funzionare per i miei scopi * senza di me dover conoscere un eccesso circa i primi tre byte di codifica del testo e le situazioni in cui tali dati non sono informativi.

* I miei scopi sono:

  1. Possedere uno snippet senza dipendenza utilizzabile con un livello medio-alto di successo,
  2. Analizzare una stazione di lavoro locale per i file di registro basati su testo di qualsiasi codifica e identificarli come file a cui sono interessato in base al loro contenuto (che richiede l'apertura del file con la codifica corretta)
  3. per la sfida di far funzionare tutto questo.

Domanda: Quali sono le insidie ​​con l'utilizzo di un quello che presumo di essere un metodo klutzy di confronto e contando personaggi come faccio io qui di seguito? Qualsiasi input è molto apprezzato.

def guess_encoding_debug(file_path): 
    """ 
    DEBUG - returns many 2 value tuples 
    Will return list of all possible text encodings with a count of the number of chars 
    read that are common characters, which might be a symptom of success. 
    SEE warnings in sister function 
    """ 

    import codecs 
    import string 
    from operator import itemgetter 

    READ_LEN = 1000 
    ENCODINGS = ['ascii','cp1252','mac_roman','utf_8','utf_16','utf_16_le',\ 
       'utf_16_be','utf_32','utf_32_le','utf_32_be'] 

    #chars in the regular ascii printable set are BY FAR the most common 
    #in most files written in English, so their presence suggests the file 
    #was decoded correctly. 
    nonsuspect_chars = string.printable 

    #to be a list of 2 value tuples 
    results = [] 

    for e in ENCODINGS: 
     #some encodings will cause an exception with an incompatible file, 
     #they are invalid encoding, so use try to exclude them from results[] 
     try: 
      with codecs.open(file_path, 'r', e) as f: 

       #sample from the beginning of the file 
       data = f.read(READ_LEN) 

       nonsuspect_sum = 0 

       #count the number of printable ascii chars in the 
       #READ_LEN sized sample of the file 
       for n in nonsuspect_chars: 
        nonsuspect_sum += data.count(n) 

       #if there are more chars than READ_LEN 
       #the encoding is wrong and bloating the data 
       if nonsuspect_sum <= READ_LEN: 
        results.append([e, nonsuspect_sum]) 
     except: 
      pass 

    #sort results descending based on nonsuspect_sum portion of 
    #tuple (itemgetter index 1). 
    results = sorted(results, key=itemgetter(1), reverse=True) 

    return results 


def guess_encoding(file_path): 
    """ 
    Stupid, simple, slow, brute and yet slightly accurate text file encoding guessing. 
    Will return one likely text encoding, though there may be others just as likely. 
    WARNING: DO NOT use if your file uses any significant number of characters 
      outside the standard ASCII printable characters! 
    WARNING: DO NOT use for critical applications, this code will fail you. 
    """ 

    results = guess_encoding_debug(file_path) 

    #return the encoding string (second 0 index) from the first 
    #result in descending list of encodings (first 0 index) 
    return results[0][0] 

Io parto dal presupposto che sarebbe stato lento rispetto a chardet, che io non sono particolarmente familiare. Anche meno preciso. Il modo in cui è progettato, qualsiasi linguaggio basato su caratteri romani che usi accenti, dieresi, ecc. Non funzionerà, almeno non bene. Sarà difficile sapere quando fallisce. Tuttavia, la maggior parte del testo in inglese, inclusa la maggior parte del codice di programmazione, sarebbe in gran parte scritta con string.printable da cui dipende questo codice.

librerie esterne possono essere un'opzione in futuro, ma per ora voglio evitare loro perché:

  1. Questo script verrà eseguito su più computer aziendali e disattivare la rete con le varie versioni di pitone, quindi, meno complicazioni, meglio è. Quando dico "compagnia" intendo piccole organizzazioni non profit di sociologi.
  2. Sono incaricato di raccogliere i registri dall'elaborazione dei dati GPS, ma non sono l'amministratore di sistema - lei non è un programmatore python e meno tempo ho a disposizione di lei, meglio è.
  3. L'installazione di Python che è generalmente disponibile presso la mia azienda è installata con un pacchetto software GIS ed è generalmente meglio se lasciata sola.
  4. I miei requisiti non sono troppo rigidi, voglio solo identificare i file che mi interessano e utilizzare altri metodi per copiarli in un archivio. Non sto leggendo l'intero contenuto in memoria per manipolare, accodare o riscrivere i contenuti.
  5. Sembra che un linguaggio di programmazione di alto livello dovrebbe avere un modo per realizzare questo da solo. Mentre "sembra" è un fondamento traballante per qualsiasi impresa, volevo provare a vedere se potevo farlo funzionare.
+0

+1 per una domanda ben scritta! esempio ben studiato e ben scritto. –

+1

Qualche motivo per non provare una libreria esistente? Come chardet o chared (https://code.google.com/p/chared/)? – amit

+0

Da quello che ho capito ci sono alcune ottime librerie disponibili per questo tipo, come quelle che hai menzionato. Spero di avere il tempo di imparare a usarli come sono sicuro che sono più potenti di quello che posso inventare. Tuttavia, ci sono molti motivi per evitare una libreria esterna. Ho modificato il mio post per indicare meglio le mie ragioni. –

risposta

0

Probabilmente il modo più semplice per scoprire il funzionamento del codice è quello di utilizzare le suite di test per le altre librerie esistenti e utilizzarle come base per creare la propria suite di test completa.Loro sapranno se il tuo codice funziona per tutti questi casi e puoi anche testare tutti i casi che ti interessano.

Problemi correlati