5

与 Python 或文本编码相比,我对自行车维修、电锯使用和沟槽安全的了解更多;考虑到这一点...

Python 文本编码似乎是一个长期存在的问题(我自己的问题:Searching text files' contents with various encodings with Python?和其他我读过的:1 , 2。我已经尝试编写一些代码来猜测编码如下。

在有限的测试中,这段代码似乎适用于我的目的*,而我不必知道文本编码的前三个字节以及这些数据不提供信息的情况。

*我的目的是:

  1. 有一个无依赖的片段,我可以使用并获得中等程度的成功,
  2. 扫描本地工作站以查找任何编码的基于文本的日志文件,并根据其内容将它们识别为我感兴趣的文件(这需要使用正确的编码打开文件)
  3. 让这个工作的挑战。

问题:使用我认为是比较和计数字符的笨拙方法有什么陷阱,就像我在下面做的那样?非常感谢任何输入。

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 编写的。

将来可能会选择外部库,但现在我想避免使用它们,因为:

  1. 该脚本将使用各种版本的 python 在网络上和网络外的多台公司计算机上运行,​​因此复杂性越少越好。当我说“公司”时,我指的是社会科学家的小型非营利组织。
  2. 我负责从 GPS 数据处理中收集日志,但我不是系统管理员——她不是 python 程序员,我花的时间越少越好。
  3. 我公司普遍提供的Python安装是随GIS软件包一起安装的,一般不用管会更好。
  4. 我的要求并不太严格,我只是想识别出我感兴趣的文件,并使用其他方法将它们复制到存档中。我没有将全部内容读入内存来操作、附加或重写内容。
  5. 似乎高级编程语言应该有某种方式自行完成此任务。虽然“似乎”对于任何努力来说都是一个摇摇欲坠的基础,但我想尝试看看我是否能让它发挥作用。
4

1 回答 1

0

了解您的代码运行情况的最简单方法可能是采用其他现有库的测试套件,并以此为基础创建您自己的综合测试套件。他们将知道您的代码是否适用于所有这些情况,并且您还可以测试您关心的所有情况。

于 2013-10-07T16:06:00.137 回答