【问题标题】:How do I detect missing fields in a CSV file in a Pythonic way?如何以 Pythonic 方式检测 CSV 文件中的缺失字段?
【发布时间】:2010-11-19 17:00:28
【问题描述】:

我正在尝试使用 Python 的 csv 模块(特别是 DictReader 类)解析 CSV 文件。有没有一种 Pythonic 方法来检测空字段或缺失字段并引发错误?

这是一个使用以下标头的示例文件:NAME、LABEL、VALUE

foo,bar,baz
yes,no
x,y,z

解析时,我希望第二行抛出错误,因为它缺少 VALUE 字段。

这是一个代码 sn-p,它显示了我是如何处理这个的(忽略硬编码的字符串......它们只是为了简洁而存在):

import csv

HEADERS = ["name", "label", "value" ]
fileH = open('configFile')
reader = csv.DictReader(fileH, HEADERS)

for row in reader:
    if row["name"] is None or row["name"] == "":
        # raise Error
    if row["label"] is None or row["label"] == "":
        # raise Error
    ...
fileH.close()

有没有一种更简洁的方法来检查 CSV 文件中的字段而没有一堆 if 语句?如果我需要添加更多字段,我还需要更多条件,如果可能的话我想避免。

【问题讨论】:

    标签: python error-handling csv


    【解决方案1】:
    if any(row[key] in (None, "") for key in row):
        # raise error
    

    编辑:更好:

    if any(val in (None, "") for val in row.itervalues()):
        # raise error
    

    【讨论】:

    • 此方法与 csv.DictReader 的行为几乎不兼容。它将遍历行中的所有键,即使其中一些可能被 DictReader 丢弃,因为它们没有在 HEADERS 中明确提及。更多信息:docs.python.org/library/csv.html#csv.DictReader
    • @Triptych:最多有一个这样的附加键(作为 restkey 传递给构造函数的值)。我看不出有什么问题。
    • @balpha,在我看来,如果 CSV 行中有额外的字段,DictReader 会忽略它们,因为没有任何东西传递给 restkey,但你的代码会引发错误。在我看来,这破坏了 DictReader 的一个功能。
    • @Triptych:我刚试过;它按预期工作。如果没有作为 restkey 传递,则使用默认键 (None)。由于此键的值始终是一个序列,因此 (None, "") 中的 val 应为 False。
    • @balpha,您的第二次编辑正是我想要的。如果在文件中添加了一个额外的字段,我实际上更喜欢它。谢谢!
    【解决方案2】:

    由于None 和空字符串的计算结果都为False,您应该考虑这一点:

    for row in reader:
        for header in HEADERS:
            if not row[header]:
                # raise error
    

    请注意,与其他一些答案不同,您仍然可以选择提出信息丰富的、特定于标头的错误。

    【讨论】:

    • 如果您在任何列中有数字 0 值,并且 quoting 设置为 csv.QUOTE_NONNUMERIC,这将导致误报。
    【解决方案3】:

    这样的?

    ...
    for row in reader:
        for column, value in row.items():
            if value is None or value == "":
                # raise Error, using value of column to say which field is missing
    

    您可以使用 'if not value:' 作为测试,而不是您给出的更明确的测试。

    【讨论】:

      【解决方案4】:

      此代码将为每一行提供该行不存在(或为空)的字段名称列表。然后,您可以提供更详细的异常,例如“缺少字段:foo、baz”。

      def missing(row):
          return [h for h in HEADERS if not row.get(h)]
      
      for row in reader:
          m = missing(row)
          if missing:
              # raise exception with list of missing field names
      

      【讨论】:

        【解决方案5】:

        如果您使用 matplotlib.mlab.csv2rec,它已经将文件的内容保存到一个数组中,如果其中一个值丢失,则会引发错误。

        >>> from matplotlib.mlab import csv2rec
        >>> content_array = csv2rec('file.txt')
        IndexError: list index out of range
        

        问题在于没有一种简单的方法可以自定义此行为,或者在缺少行的情况下提供默认值。此外,错误消息不是很容易解释(在此处发布错误报告可能很有用)。

        附言由于 csv2rec 将文件的内容保存到 numpy 记录中,因此更容易获得等于 None 的值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-09-05
          • 1970-01-01
          • 1970-01-01
          • 2017-04-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多