【问题标题】:python csv writer if row key does not existpython csv writer如果行键不存在
【发布时间】:2016-08-02 14:58:10
【问题描述】:

以下脚本出错:

import csv,time,string,os,requests, datetime

test = "\\\\network\\Shared\\test.csv"

fields = ["id", "Expiration Date", "Cost", "Resale" ]

with open(test) as infile, open("c:\\upload\\tested.csv", "wb") as outfile:
    r = csv.DictReader(infile)
    w = csv.DictWriter(outfile, fields, extrasaction="ignore")
    r = (dict((k, v.strip()) for k, v in row.items() if v) for row in r)

    wtr = csv.writer( outfile )                                                                                                                                                                                                                                                                                                                                         
    wtr.writerow(["id", "upload_date", "cost", "resale"])
    for i, row in enumerate(r, start=1):
        row['id'] = i
        print(row['Expiration Date']
        row['Expiration Date'] = datetime.datetime.strptime(row['Expiration Date'][:10], "%m/%d/%Y").strftime("%Y-%m-%d")
        w.writerow(row)


D:\Python\Scripts>python test.py
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    print(row['Expiration Date'])
KeyError: 'Expiration Date'

所以我想我明白发生了什么 - 来自原始文件的类似内容:

Expiration Date     Cost     Resale
2016-01-01          1.00     2.00
                    1.42     2.42
2016-05-02          1.45     9.00

据我所知,有一行没有填充到期日期列。如何强制 DictWriter 跳过空白 - 假设这是我的错误的原因?

【问题讨论】:

    标签: python


    【解决方案1】:

    实际上,csv.DictReader 生成的dict 只是将None 放入它找不到的字段中,因此您不应该收到该错误。您没有使用DictReader 的功能来生成正确的dict!据我所知,您尝试使用r = (dict((k, v.strip()) for k, v in row.items() if v) for row in r) 行自己进行解析。但是,这实际上不起作用。如果您之后打印这些行,您会得到:

    {'Expiration Date     Cost     Resale': '2016-01-01          1.00     2.00'}
    {'Expiration Date     Cost     Resale': '1.42     2.42'}
    {'Expiration Date     Cost     Resale': '2016-05-02          1.45     9.00'}
    

    所以每个dict 只包含一个密钥。您的文件的一个问题是,您在行之间没有有效的分隔符。看起来您的意思是使用空格,但Expiration Date 中也有空格。你将不得不摆脱它。如果你这样做,那么你可以像这样使用DictReader

    import csv,time,string,os,requests, datetime
    
    test = "test.csv"
    
    with open(test) as infile:
        r = csv.DictReader(infile, delimiter=" ", skipinitialspace=True)
    for row in r:
        print(row)
    

    现在给你:

    {'Resale': '2.00', 'Cost': '1.00', 'ExpirationDate': '2016-01-01'}
    {'Resale': None, 'Cost': '2.42', 'ExpirationDate': '1.42'}
    {'Resale': '9.00', 'Cost': '1.45', 'ExpirationDate': '2016-05-02'}
    

    这是一个正确的dict(请注意,读者无法知道第一个元素是缺失的元素)。现在您只需从写入中排除不完整的行。描述了一个很好的方法here

    import csv,time,string,os,requests, datetime
    
    test = "test.csv"
    
    with open(test) as infile:
        r = csv.DictReader(infile, delimiter=" ", skipinitialspace=True)
    
        for row in r:
            if not any(val in (None, "") for val in row.itervalues()):
                print(row)
    

    最后,这将为您提供dicts 的所有有效行:

    {'Resale': '2.00', 'Cost': '1.00', 'ExpirationDate': '2016-01-01'}
    {'Resale': '9.00', 'Cost': '1.45', 'ExpirationDate': '2016-05-02'}
    

    【讨论】:

    • 我并不真正理解 r = (dict((k, v.strip()) for k, v in row.items() if v) for row in r) 行 - 代码本身来自我写的关于在写入每个值之前修剪每个值的空白的 SO 帖子,但你是对的,当我删除该行,它解决了发生这种特殊情况的问题 - 但是代码是剥离空白,所以现在我需要找到一种新方法来从我的输出文件中修剪空白......
    • @BrianPowell 我在示例中使用的skipinitialspace=True参数去除了所有前导空格。这不是你需要的吗?
    • 我在工作表中有几个值(就像 50 列,而不是我在这里显示的 3 列),它们的开头或结尾有空格:`你好`-代码来自我上面的cmets,它确实修剪了那个空白,但我想它也搞砸了我的字典。我的理解是skipinitialspace 只会从值的开头修剪空白。
    • 问题不在于该行,而是您的逗号分隔值文件中没有逗号,并且您没有指定任何其他分隔符。如果您指定delimiter=" ",那么他能够正确生成您的字典(只要没有任何键/值包含空格)。然后skipinitialspace=True 跳过所有空格,因为在条目之后将没有空格(因为条目之后的第一个空格被视为delimiter)。
    • 好的,那么您实际上可以使用类似于您拥有的线的东西。首先您必须更改delimiter=",",然后您可以插入r = [{k.strip(): v.strip() for k, v in row.items()} for row in r]。这适用于 python 2.7.2 和更新版本。然后您可以稍后使用if 子句排除所有缺少条目的rows。
    【解决方案2】:

    您在访问 x['Expiration Date'] 的字典中没有的内容时遇到 KeyError,因此您可以说 x.get('Expiration Date') 或可能是 'Expiration Date' in x 来发现它是否存在并有条件地丢弃该行。

    【讨论】:

    • 实际上,他的读入是有缺陷的,除了"Expiration Date Cost Resale" 作为key 在他的dict 中,他什么都没有。
    猜你喜欢
    • 1970-01-01
    • 2015-04-24
    • 2018-10-21
    • 2014-10-02
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 2014-07-15
    相关资源
    最近更新 更多