【问题标题】:Python string encodings and ==Python 字符串编码和 ==
【发布时间】:2012-06-02 17:38:44
【问题描述】:

当我认为 python 中的字符串不是 == 时,我遇到了一些问题,我相信这与它们的编码方式有关。基本上,我会解析一些存储在 zip 存档中的逗号分隔值(特别是 GTFS 提要,对于那些好奇的人)。

我在 python 中使用 ZipFile 模块打开某些文件和 zip 档案,然后将那里的文本与一些已知值进行比较。这是一个示例文件:

agency_id,agency_name,agency_url,agency_phone,agency_timezone,agency_lang
ARLC,Arlington Transit,http://www.arlingtontransit.com,703-228-7433,America/New_York,en

我正在使用的代码试图识别字符串“agency_id”在文本第一行中的位置,以便我可以在任何后续行中使用相应的值。这是代码的sn-p:

zipped_feed = ZipFile(feed_name, "r")
agency_file = zipped_feed.open("agency.txt", "r")

line_num = 0
agencyline = agency_file.readline()
while agencyline:
    if line_num == 0:
        # this is the header, all we care about is the agency_id
        lineparts = agencyline.split(",")
        position = -1
        counter = 0
        for part in lineparts:
            part = part.strip()
            if part == "agency_id":
                position = counter              
        counter += 1
        line_num += 1
        agencyline = agency_file.readline()
    else:
        .....

此代码适用于某些 zip 存档,但不适用于其他存档。我做了一些研究并尝试打印 repr(part),我得到了 '\xef\xbb\xbfagency_id' 而不是 'agency_id'。有谁知道这里发生了什么以及我该如何解决?感谢大家的帮助!

【问题讨论】:

  • 对不起!你做的时候我正在编辑!
  • 请注意,如果仅在第一次(或最后一次)迭代中执行代码,则在循环之前(或之后)移动该代码会更高效、更清晰。此外,您可以使用position = lineparts.index('agency_id') 在一行中查找所需字段的位置,并使用for agencyline in agency_file 循环遍历文件中的其余行。一旦您的程序正常运行,您可能希望将其发布到codereview.SE 以获得更多反馈。
  • UTF-8 文件不应有 BOM:Unicode 标准“既不要求也不推荐”它们。这闻起来像 Windows 错误。

标签: python string utf-8


【解决方案1】:

这是一个Byte Order Mark,它告诉文件的编码,在 UTF-16 和 UTF-32 的情况下,它还告诉文件的字节序。您可以解释它或检查它并将其从字符串中删除。 要删除它,您可以这样做:

import codecs

unicode(part, "utf8").lstrip(codecs.BOM_UTF8.decode("utf8", "strict"))

【讨论】:

  • 用 python 3.2.3 和 2.7.3 测试
  • 我收到以下错误:UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)
【解决方案2】:

您的输入文件似乎是 utf-8 并以 'ZERO WIDTH NO-BREAK SPACE'-character 开头,

import unicodedata
unicodedata.name('\xef\xbb\xbf'.decode('utf8'))
# gives: 'ZERO WIDTH NO-BREAK SPACE'

用作 BOM(或者更准确地说,将文件标识为 utf8,因为 utf8 的字节顺序并不准确,但它通常被称为 BOM)

【讨论】:

  • BOM 的十六进制代码与零宽度 nbsp 相同;这可能是一个 BOM。
【解决方案3】:

简单:您的一些 zip 档案在字符串的开头打印Unicode BOM (Byte Order Mark)。这用于指示用于多字节编码的字节顺序。这意味着您正在将 Unicode 字符串(可能是 UTF-16 编码)作为字节字符串读取。最简单的做法是在字符串的开头检查它并将其删除。

【讨论】:

    【解决方案4】:

    您得到的是一个文件,它的前面可能偶尔会有一个 Unicode 字节顺序标记。有时这是由编辑引入以指示编码。

    这里有一些细节 - http://en.wikipedia.org/wiki/Byte_order_mark

    底线是您可以查找作为 UTF-8 编码数据标记的 \xef\xbb\xbf 字符串,然后将其剥离。或者另一种选择是使用编解码器包打开它

    with codecs.open('input', 'r', 'utf-8') as file: 
    

    或者在你的情况下

    zipped_feed = ZipFile(feed_name, "r")
    # adding a StreamReader around the zipped_feed.open(...)
    agency_file = codecs.StreamReader(zipped_feed.open("agency.txt", "r"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-08
      • 2016-07-23
      • 1970-01-01
      • 2017-11-01
      相关资源
      最近更新 更多