2013-09-02 12 views
5

Wiem więcej o naprawie rowerów, używaniu pił łańcuchowych i bezpieczeństwie wykopów niż w Pythonie lub kodowaniu tekstu; Mając to na uwadze ...Pułapki w moim kodzie do wykrywania kodowania plików tekstowych za pomocą Pythona?

kodowanie tekstu Python wydaje się być kwestia wieloletnia (moje własne pytanie: Searching text files' contents with various encodings with Python? i inni czytałem. 1, 2 Wziąłem pęknięcia na pisanie kodu do odgadnięcia poniżej kodowania.

W ograniczonym testowania tego kodu wydaje się działać dla moich celów * bez konieczności mi znać nadmiar około trzech pierwszych bajtów kodowania tekstu i sytuacji, w których dane te nie są pouczające.

* Moje cele to:

  1. Posiadam wolny od zależności fragment, którego mogę używać z umiarkowanym wysokim poziomem powodzenia,
  2. Skanuj lokalną stację roboczą dla plików tekstowych opartych na protokołach dowolnego kodowania i oznacz je jako plik, który mnie interesuje w oparciu o ich zawartość (który wymaga otwarcia pliku z odpowiednim kodowaniem)
  3. za wyzwanie, aby to zadziałało.

Pytanie: Jakie są pułapki z użyciem co zakładam być klutzy metoda porównywania i liczenia znaków jak to zrobić poniżej? Wszelkie dane wejściowe są bardzo doceniane.

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] 

jestem przy założeniu, że będzie powolny w porównaniu do chardet, której nie jestem szczególnie znane. Również mniej dokładne. Sposób, w jaki jest zaprojektowany, jakikolwiek język bazujący na języku rzymskim, który używa akcentów, umlautów itp. Nie będzie działać, a przynajmniej nie będzie dobrze. Trudno będzie się zorientować, kiedy się nie uda. Jednak większość tekstów w języku angielskim, w tym większość kodu programistycznego, będzie w większości napisana za pomocą string.printable, od którego zależy ten kod.

zewnętrznych bibliotek może być opcja w przyszłości, ale na razie chcę się ich unikać, ponieważ:

  1. Ten skrypt będzie uruchamiany na wielu komputerach firmowych i wyłączania sieci z różnymi wersjami Pythona, więc im mniej komplikacji, tym lepiej. Kiedy mówię "firma", mam na myśli mały non-profit z nauk społecznych.
  2. Jestem odpowiedzialny za zbieranie dzienników z przetwarzania danych GPS, ale nie jestem administratorem systemów - ona nie jest programistką Pythona i im mniej czasu poświęcam jej, tym lepiej.
  3. Instalacja Pythona, która jest ogólnie dostępna w mojej firmie, jest instalowana z pakietem oprogramowania GIS i generalnie lepiej jest, gdy pozostawi się ją samą.
  4. Moje wymagania nie są zbyt surowe, chcę tylko zidentyfikować pliki, które mnie interesują, i użyć innych metod, aby skopiować je do archiwum. Nie czytam pełnej zawartości pamięci, aby manipulować, dodawać lub przepisywać zawartość.
  5. Wygląda na to, że język programowania wysokiego poziomu powinien mieć jakiś sposób na osiągnięcie tego samodzielnie. Chociaż "wydaje się, że" jest chwiejnym fundamentem dla każdego przedsięwzięcia, chciałem sprawdzić, czy uda mi się go uruchomić.
+0

+1 za dobrze napisane pytanie! dobrze zbadany, dobrze napisany przykład. –

+1

Powody, dla których nie próbujesz istniejącej biblioteki? Jak chardet lub chared (https://code.google.com/p/chared/)? – amit

+0

Z tego co rozumiem, istnieją bardzo dobre biblioteki dostępne dla tego rodzaju, takie jak te, które wspomniałeś. Mam nadzieję, że będę miał czas, aby nauczyć się z nich korzystać, ponieważ jestem pewien, że są silniejsi niż to, co mogę wymyślić. Istnieje jednak wiele powodów, aby unikać zewnętrznej biblioteki. Zmodyfikowałem mój post, aby lepiej podać moje powody. –

Odpowiedz

0

Najprawdopodobniej najprostszym sposobem sprawdzenia, na ile działa twój kod, jest skorzystanie z zestawów testów dla innych istniejących bibliotek i użycie ich jako podstawy do stworzenia własnego kompleksowego zestawu testów.Będą wiedzieć, czy twój kod działa we wszystkich tych przypadkach, i możesz także przetestować wszystkie przypadki, na których Ci zależy.

Powiązane problemy