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:
- Posiadam wolny od zależności fragment, którego mogę używać z umiarkowanym wysokim poziomem powodzenia,
- 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)
- 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ż:
- 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.
- 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.
- 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ą.
- 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ść.
- 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ć.
+1 za dobrze napisane pytanie! dobrze zbadany, dobrze napisany przykład. –
Powody, dla których nie próbujesz istniejącej biblioteki? Jak chardet lub chared (https://code.google.com/p/chared/)? – amit
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. –