【问题标题】:python csv header ignore while keep appending data to csv filepython csv标头忽略,同时继续将数据附加到csv文件
【发布时间】:2017-03-23 13:24:05
【问题描述】:

我正在尝试将一些随机数据添加到文本文件中,并且我成功了,但我遇到了标题行的问题。我想添加一次标题行,然后每次运行我的脚本时,它应该只将数据添加到文件中,如果存在则忽略标题行。我尝试过这样的事情,但我失败了。我尝试在 SO python csv, writing headers only once 中查看此示例代码,但无法正确实现。 如果有人帮助我更正我的代码。我会很感激的。

import random
import csv
import os.path
from time import gmtime, strftime

filename = '/home/robdata/collection1.dat'

file_exists = os.path.isfile(filename)

v = random.randint(0, 100)

with open(filename, "a") as csvfile:
    headers = ['DATE', 'value']
    writer = csv.DictWriter(csvfile, delimiter=',', lineterminator='\n',fieldnames=headers)
    if not file_exists:
        writer.writeheader()  # file doesn't exist yet, write a header

    writer.writerow({'DATE': strftime("%Y-%m-%d %H:%M:%S", gmtime()), 'value': v})

它插入数据但不添加任何标题行。我想在第一次运行脚本时包含标题,下次我多次运行脚本时,它应该只添加数据而不是标题行。非常感谢任何想法或帮助。

【问题讨论】:

  • 您能否在问题中编辑对您的代码执行错误的描述?
  • @glibdud 我在我的问题下面添加。我能够将数据插入文件但没有任何标题。
  • 第一次运行(在文件存在之前),你应该得到一个 AttributeError。看看您的 csv.writer 对象与您链接的问题中使用的对象之间的区别。
  • @glibdud 我也尝试了我提到的那个例子。我根据那个例子改变了我的问题。由于我是编程新手,可能这是我在这里犯的一个非常简单的错误。
  • 这样不行吧?因为该文件仍然存在。请注意,您的代码询问文件是否存在,而不是询问文件是否为空。

标签: python csv


【解决方案1】:

埃文斯先生方法的一个稍微简单的替代方法是使用以下测试代替存在测试:

fileEmpty = os.stat('collection1.dat').st_size == 0

这消除了进行搜索等操作的需要。

编辑:完整代码:

import random
import csv
import os.path
from time import gmtime, strftime

filename = '/home/robdata/collection1.dat'

fileEmpty = os.stat(filename).st_size == 0

v = random.randint(0, 100)

with open(filename, "a") as csvfile:
    headers = ['DATE', 'value']
    writer = csv.DictWriter(csvfile, delimiter=',', lineterminator='\n',fieldnames=headers)
    if fileEmpty:
        writer.writeheader()  # file doesn't exist yet, write a header

    writer.writerow({'DATE': strftime("%Y-%m-%d %H:%M:%S", gmtime()), 'value': v})

【讨论】:

  • 非常感谢您的帮助。根据我的要求,问题中的上述代码可以正常工作。感谢您的帮助。
  • 您是否要粘贴答案以便我接受,因为您首先编辑了我的问题代码并且它工作正常。我问你是因为你先编辑它。
  • 不客气。如果这个答案对您有所帮助,那么 SO 的礼仪就是让您将其标记为“已接受”。当您获得更多积分时,您将被允许投票。
  • 当然可以。
  • 我的意思是我的问题中的代码是由你编辑的,它工作得很好。如果您只是粘贴该代码,我会接受您的回答
【解决方案2】:

除了测试文件是否存在之外,您还可以通过寻找到末尾并询问文件位置(当然仍然需要附加)来检查文件的长度是否为零。

这种方法也会在文件为空但仍然存在的情况下写入标题。它还避免了需要import os 单独创建os.stat() 来确定文件大小:

import random
import csv
from time import gmtime, strftime
    
headers = ['DATE', 'value']
v = random.randint(0, 100)
    
with open('collection1.dat', 'a', newline='') as f_output:
    csv_output = csv.DictWriter(f_output, fieldnames=headers)
    f_output.seek(0, 2)
    
    if f_output.tell() == 0:
        csv_output.writeheader()

    csv_output.writerow({'DATE': strftime("%Y-%m-%d %H:%M:%S", gmtime()), 'value': v})        

writeheader() 仅在文件为空时才用于写入标头。


注意:如果 Python 2.x 仍在使用,您应该始终以二进制模式打开文件,例如ab如下:

with open('collection1.dat', 'ab') as f_output:

【讨论】:

  • 我喜欢这个解决方案,而不是做其他检查文件是否存在,如果它是 0 等等。
  • 很好的解决方案。
【解决方案3】:

根据 Python CSV 模块的文档,writeheader 只能与 DictWriter 一起使用。 [https://docs.python.org/2/library/csv.html#csv.DictWriter.writeheader][Documentation 的 writeheader]

因此,代码不应使用writeheader。 你可以试试这个。

if not file_exists:
    writer.writerow(headers)
else:
    writer.writerow([strftime("%Y-%m-%d %H:%M:%S", gmtime()), v, w, z])

【讨论】:

  • 我编辑我的问题。但我之前尝试过这个想法,我得到了这个错误。 ValueError: dict contains fields not in fieldnames: '2017-03-23 13:59:39', 94
【解决方案4】:

看起来您在我们发布答案时编辑了您的问题。请添加任何更改作为编辑或提及您所做的更改。无论如何,虽然 dict 字段不同,但概念是相同的。

dictwriter 之上,您需要将行数据作为值传递给每一列的dict 键。

我为 5 次延迟 5 秒的写入添加了一个循环作为示例。
见下文。

工作代码:

import random
import csv
import os.path
from time import gmtime, strftime, sleep

filename = 'collection1.csv'

file_exists = os.path.isfile(filename)

v = random.randint(0, 100)
w = random.randint(0, 100)
z = random.randint(0, 100)
with open(filename, "a") as csvfile:
    for i in range(5):        
        headers = ['timestamp','val1', 'val2', 'val3']
        writer = csv.DictWriter(csvfile, delimiter=',', lineterminator='\n',fieldnames=headers)
        if not file_exists:
            writer.writeheader()
        else:
            mytime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
            writer.writerow({'timestamp':mytime, 'val1': v,'val2': w, 'val3':z})

        sleep(5)

collection1.csv

timestamp,val1,val2,val3
2017-03-23 14:07:20,83,60,11
2017-03-23 14:07:25,83,60,11
2017-03-23 14:07:30,83,60,11
2017-03-23 14:07:47,55,44,88
2017-03-23 14:07:52,55,44,88
2017-03-23 14:07:57,55,44,88
2017-03-23 14:08:02,55,44,88
2017-03-23 14:08:07,55,44,88

【讨论】:

  • 我尝试了您的代码,但得到了相同的结果。等等,我将再次检查代码。我很快就会回来更新。非常感谢您的帮助。
  • 按原样复制/粘贴我的代码。它对我有用。这是你的旧代码(修改)。让我知道。
  • @accept 我没有通知我的道歉并补充说我编辑了我的代码。下次我会小心的。
  • 您的代码运行良好。它还在运行中创建标题,然后在后续运行中添加数据。非常感谢您的帮助。
  • @rob ,很高兴为您提供帮助。如果它解决了您的问题,您是否介意接受答案以关闭循环。
【解决方案5】:

如果您将 pandas DataFrame 附加到 csv 文件,并且只想在第一次写出时保留标题,这对我有用,比以前的解决方案简单得多:

start = 100
with open('path_to_your_csv', "r",encoding = 'UTF-8') as myfile:
    reader = csv.DictReader(myfile)
    for i,line in itertools.islice(enumerate(reader) , start, 105): # iterate through row 100:105
    df # this is the data frame you want to export
    if i == start:
        df.iloc[0:0].to_csv(recent,sep = ",") # keep only header if this is the first you export
    df.to_csv(total,sep = ",",header =False)                                  
    del df

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-21
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 2019-12-01
    相关资源
    最近更新 更多