将文件名添加为CSV文件的最后一列

5 投票
6 回答
4623 浏览
提问于 2025-04-16 15:56

我有一个Python脚本,它会修改一个CSV文件,把文件名加到最后一列:

import sys
import glob

for filename in glob.glob(sys.argv[1]):
    file = open(filename)
    data = [line.rstrip() + "," + filename for line in file]
    file.close()

    file = open(filename, "w")
    file.write("\n".join(data))
    file.close()

不过,它还把文件名加到了文件的表头(第一行)。我想在表头那里加上“ID”这个字符串。有没有人能建议我该怎么做?

6 个回答

1

你可以试试:

data = [file.readline().rstrip() + ",id"]
data += [line.rstrip() + "," + filename for line in file]
5

以下是对你当前代码的一些小建议:

  • 使用 file 作为变量名并不好,因为这会和内置类型冲突。
  • 你可以使用 with 语法来自动关闭文件对象。
  • 你是不是想在表头加一个额外的列,比如叫 Filename,而不是在第一行省略一列呢?
  • 如果你的文件名中有逗号(或者不太可能的换行符),你需要确保文件名是用引号括起来的——光是直接加上去是没用的。

考虑到最后一点,我建议你使用 csv 模块,这样可以帮你处理引号的问题。例如,你可以试试下面的代码:

import glob
import csv
import sys

for filename in glob.glob(sys.argv[1]):
    data = []
    with open(filename) as finput:
        for i, row in enumerate(csv.reader(finput)):
            to_append = "Filename" if i == 0 else filename
            data.append(row+[to_append])
    with open(filename,'wb') as foutput:
        writer = csv.writer(foutput)
        for row in data:
            writer.writerow(row)

这可能会以稍微不同的方式给数据加引号,所以你可能需要调整一下 csv.readercsv.writer 的引号选项,具体可以参考 csv模块的文档

另外,你可能有很好的理由选择用 glob 作为参数,而不是直接用命令行中的文件,但这有点让人意外——你需要像这样调用你的脚本 ./whatever.py '*.csv',而不能直接用 ./whatever.py *.csv。相反,你可以这样做:

for filename in sys.argv[1:]:

... 让 shell 在脚本知道之前先展开你的 glob。

最后一点,你现在的做法有点危险,因为如果在写回同一个文件名时出现任何问题,你会丢失数据。避免这种情况的标准方法是先写入一个临时文件,如果成功了,再把临时文件重命名为原来的文件。所以,你可以把整个过程改写成:

import csv
import sys
import tempfile
import shutil

for filename in sys.argv[1:]:
    tmp = tempfile.NamedTemporaryFile(delete=False)
    with open(filename) as finput:
        with open(tmp.name,'wb') as ftmp:
            writer = csv.writer(ftmp)
            for i, row in enumerate(csv.reader(finput)):
                to_append = "Filename" if i == 0 else filename
                writer.writerow(row+[to_append])
    shutil.move(tmp.name,filename)
5

你可以看看官方的csv模块

撰写回答