假设你有一个枯燥的任务,要删除几百CSV文件的第一行。 也许你会将它们送入一个自动化的过程,只需要数据, 不需要每列顶部的表头。可以在Excel中打开每个文件, 删除第一行,并重新保存该文件,但这需要几个小时。 让我们写一个程序来做这件事。
该程序需要打开当前工作目录中所有扩展名为.csv的文件, 读取CSV文件的内容,并除掉第一行的内容重新写入同名的 文件。这将用新的、无表头的内容替换CSV文件的旧内容。
警告
与往常一样,当你写程序修改文件时,一定要先备份这些 文件,以防万一你的程序没有按期望的方式工作。你不希望 意外地删除原始文件。
总的来说,该程序必须做到以下几点:
找出当前工作目录中的所有CSV文件。
读取每个文件的全部内容。
跳过第一行,将内容写入一个新的CSV文件。
在代码层面上,这意味着该程序需要做到以下几点:
循环遍历从 os.listdir() 得到的文件列表,跳过非CSV文件。
创建一个 CSV Reader 对象,读取该文件的内容,利用 line_num 属性确定要跳过哪一行。
创建一个 CSV Writer 对象,将读入的数据写入新文件。
针对这个项目,打开一个新的文件编辑器窗口,并保存为removeCsvHeader.py 。
程序需要做的第一件事情,就是循环遍历当前工作 目录中所有CSV文件名的列表。 让 removeCsvHeader.py 看起来像这样:
#! python3
#removeCsvHeader.py - Removes the header from all CSV files in the current
#working directory.
import csv, os
os.makedirs(‘headerRemoved’, exist_ok=True)
#Loop through every file in the current working directory.
for csvFilename in os.listdir(‘.’):
if not csvFilename.endswith(‘.csv’):
continue # skip non-csv files
print('Removing header from ' + csvFilename + '...')
# TODO: Read the CSV file in (skipping first row).
# TODO: Write out the CSV file.
os.makedirs() 调用将创建 headerRemoved 文件夹, 所有的无表头的CSV文件将写入该文件夹。 针对 os.listdir(‘.’)进行 for 循环完成了一部分 任务,但这会遍历工作目录中的所有文件,所以需要在循环 开始处添加一些代码,跳过扩展名不是 xsv 的文件。 如果遇到非 CSV 文件, continue 语句O让循环 转向下一个文件名。
为了让程序运行时有一些输出,打印出一条消息说明程序 在处理哪个CSV文件。然后,添加一些 TODO 注释, 说明程序的其余部分应该做什么。
该程序不会从原来的CSV文件删除第一行。但是,它会创 建新的CSV文件副本,不包含第一行。因为副本的文件名 与原来的文件名一样,所以副本会覆盖原来的文件。
该程序需要一种方法,来知道它的循环当前是否在处理 第一行。为 removeCsvHeader.py添加以下代码。
#! python3
#removeCsvHeader.py - Removes the header from all CSV files in the current
#working directory.
–snip–
#Read the CSV file in (skipping first row).
csvRows =[]
csvFileObj = open(csvFilename)
readerObj = csv.reader(csvFileObj)
for row in readerObj:
if readerObj.line_num == 1:
continue # skip first row
csvRows.append(row)
csvFileObj.close()
#TODO: Write out the CSV file.
Reader 对象的 line_num 属性可以用来确定当前 读入的是CSV文件的哪一行。另一个 for 循环会遍历 CSV Reader 对象返回所有行,除了第一行,所有行都 会添加到csvRows 中
在 for 循环遍历每一行时,代码检查 reader.line_num 是否设为1。如果是这样,它执行 continue ,转向下一行, 不将它添加到 csvRows 中。对于之后的每一行,条 件永远是 False ,该行将添加到 csvRows 中。
现在csvRows 包含了除第一行的所有行,该列表需要写入 headerRemoved 文件夹中的一个CSV文件。将以下代码添 加到 removeCsvHeader.py :
#! python3
removeCsvHeader.py - Removes the header from all CSV files in the current
working directory.
import csv, os
os.makedirs(‘headerRemoved’, exist_ok=True)
Loop through every file in the current working directory.
for csvFilename in os.listdir(‘.’):
if not csvFilename.endswith(‘.csv’):
continue # skip non-csv filesprint('Removing header from ' + csvFilename + '...') # Read the CSV file in (skipping first row). csvRows = [] csvFileObj = open(csvFilename) readerObj = csv.reader(csvFileObj) for row in readerObj: if readerObj.line_num == 1: continue # skip first row csvRows.append(row) csvFileObj.close() # Write out the CSV file. csvFileObj = open(os.path.join('headerRemoved', csvFilename), 'w', newline='') csvWriter = csv.writer(csvFileObj) for row in csvRows: csvWriter.writerow(row) csvFileObj.close()
Removing header from NAICS_data_3495.csv…
Removing header from NAICS_data_6493.csv…
Removing header from NAICS_data_9103.csv…
Removing header from NAICS_data_8499.csv…
Removing header from NAICS_data_5899.csv…
Removing header from NAICS_data_3044.csv…
Removing header from NAICS_data_5060.csv…
CSV Writer对象利用csvFilename (这也是我们在 CSV Reader中使用的文件名),将列表写入 headerRemoved 中的一个 CSV 文件。这将覆盖 原来的文件。创建Writer对象后,我们循环遍历存储 在csvRows中的子列表,将每个子列表写入该文件。
这段代码执行后,外层 for 循环将循环到 os.listdir(‘.’) 中的下一个文件名。 循环结束时,程序就结束了。
为了测试你的程序,从http://nostarch.com/automatestuff/ 下载removeCsvHeader.zip,将它解压缩到一个文件夹。 在该文件夹中运行 removeCsvHeader.py 程序。 输出将是这样的:
这个程序应该在每次从 CSV 文件中删除第一行时, 打印一个文件名。
针对 CSV 文件写的程序类似于针对 Excel 文件写的 程序,因为它们都是电子表格文件。你可以编程完成以下任务:
在一个 CSV 文件的不同行,或多个 CSV 文件之间比较数据。
从 CSV 文件拷贝特定的数据到Excel文件,或反过来。
检查 CSV 文件中无效的数据或格式错误,并向用户提醒这些错误。
从 CSV 文件读取数据,作为Python程序的输入。