简体   繁体   English

python csv标头忽略,同时继续将数据附加到csv文件

[英]python csv header ignore while keep appending data to csv file

I am trying to add some random data into text file and I am successful in that but I am facing problem with the header line.我正在尝试将一些随机数据添加到文本文件中,并且我成功了,但是我遇到了标题行的问题。 I want to add header line once and then every time I run my script , it should add just data into file and ignore the header line if exists.我想添加一次标题行,然后每次运行我的脚本时,它应该只将数据添加到文件中,并忽略标题行(如果存在)。 I tried something like this but I fail.我试过这样的事情,但我失败了。 I try to look at this example code in SO python csv, writing headers only once , but couldn't implement properly.我尝试在 SO python csv 中查看此示例代码, 仅写入一次标题,但无法正确实现。 If somebody help me to correct my code.如果有人帮我纠正我的代码。 I will be thankful.我会很感激的。

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})

it insert data but without adding any header line.它插入数据但不添加任何标题行。 I want to include headers on the first run of script, and next time when I run script several times , it should only add data and not header line.我想在第一次运行脚本时包含标题,下次我多次运行脚本时,它应该只添加数据而不是标题行。 thank a lot for any idea or help.非常感谢任何想法或帮助。

A slightly simpler alternative to Mr Evans approach would be to use the following test in place of the test for existence:埃文斯先生方法的一个稍微简单的替代方法是使用以下测试代替存在测试:

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

This obviates the need to do a seek, etc.这消除了进行搜索等的需要。

EDIT: Complete code:编辑:完整代码:

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})

Rather than testing if the file exists, you could instead check to see if has zero length by seeking to the end and asking for the file location (which is of course still needed to append).与其测试文件是否存在,您还可以通过查找到末尾并询问文件位置(当然仍然需要追加)来检查文件是否具有零长度。

This approach will then also write the header for the case when the file is empty but still exists.当文件为空但仍然存在时,此方法还将为这种情况写入标头。 It also avoids needing to import os to make a separate os.stat() to determine the file size:它还避免了需要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() is then used to write the header only when the file is empty. writeheader()仅在文件为空时才用于写入标头。


Note: If Python 2.x is still in use, you should always open the file in binary mode eg ab as follows:注意:如果 Python 2.x 仍在使用,您应该始终以二进制模式打开文件,例如ab ,如下所示:

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

From the documentation of Python CSV module, writeheader can be used only with DictWriter.从 Python CSV 模块的文档中, writeheader只能与 DictWriter 一起使用。 [ https://docs.python.org/2/library/csv.html#csv.DictWriter.writeheader][Documentation of writeheader] [ https://docs.python.org/2/library/csv.html#csv.DictWriter.writeheader][writeheader文档]

Hence, the code should not be using writeheader .因此,代码不应使用writeheader You can try this.你可以试试这个。

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

Looks like you edited your question while we were posting answer.看起来您在我们发布答案时编辑了您的问题。 Please add any changes as edit or mention what you have changed.请添加任何更改作为编辑或提及您已更改的内容。 Anyway, while dict fields are different, concept is same.无论如何,虽然 dict 字段不同,但概念是相同的。

On top of dictwriter , you need to pass row data as values to the dict keys for each column.dictwriter ,您需要将行数据作为值传递给每列的 dict 键。

I added a loop for 5 writes delayed by 5 sec as sample.我添加了一个延迟 5 秒的 5 次写入循环作为示例。
See below.见下文。

Working Code:工作代码:

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集合1.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

In case that you are appending pandas DataFrame to a csv file, and want to keep the header only at the first time you write out, here is what worked for me, much simpler than solutions before:如果您将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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM