我对自行车维修、电锯使用和沟渠安全的了解比对Python或文本编码的了解更多。鉴于此,Python文本编码似乎是一个长期存在的问题(我的问题:在Python中搜索各种编码的文本文件内容?和其他我读过的问题:1,2)。我尝试编写一些代码来猜测编码。
我认为与我不太熟悉的chardet相比,它可能会慢一些,并且不够准确。它的设计方式导致任何基于罗马字符的带有重音、分音符等语言都不能很好地工作。这就使得当它失效时很难知道。然而,大部分英文文本,包括大多数编程代码,都是使用此代码所依赖的string.printable来编写的。
未来,使用外部库可能是一个选择,但目前我想避免这样做,因为:
在有限的测试中,这段代码似乎可以在不需要我过多了解文本编码的前三个字节以及那些数据不提供信息的情况下达到我的目的*。
*我的目的是:
- 拥有一个无需依赖的片段,我可以用它来实现中高度成功率,
- 扫描本地工作站上的任何编码的基于文本的日志文件,并根据其内容将其识别为我感兴趣的文件(这需要使用正确的编码打开文件)
- 挑战自己,让它能够正常工作。
问题:使用我下面所做的比较和计数字符的笨拙方法有什么缺陷?非常感谢您提供任何意见。
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]
我认为与我不太熟悉的chardet相比,它可能会慢一些,并且不够准确。它的设计方式导致任何基于罗马字符的带有重音、分音符等语言都不能很好地工作。这就使得当它失效时很难知道。然而,大部分英文文本,包括大多数编程代码,都是使用此代码所依赖的string.printable来编写的。
未来,使用外部库可能是一个选择,但目前我想避免这样做,因为:
- 这个脚本将在公司内外的多台计算机上运行,这些计算机使用不同版本的Python,因此越简单越好。当我说“公司”时,我指的是由社会科学家组成的小型非营利组织。
- 我负责收集GPS数据处理日志,但我不是系统管理员,她不是Python程序员,我占用她的时间越少越好。
- 我的公司通常安装Python的版本是与GIS软件包一起安装的,如果让它保持原样通常会更好。
- 我的需求并不是特别严格,我只想识别出我感兴趣的文件,并使用其他方法将它们复制到归档中。我并不是将整个内容读入内存进行操作,也不是将其附加或重写。
- 高级编程语言应该有一些自己的方法来完成这项任务。虽然“似乎”是任何事业的不稳定基础,但我想尝试并看看是否可以让它工作。