Добавить имя файла в качестве последнего столбца файла CSV - PullRequest
4 голосов
/ 18 апреля 2011

У меня есть скрипт 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 ]

6 голосов
/ 18 апреля 2011

Посмотрите на официальный модуль CSV .

5 голосов
/ 18 апреля 2011

Вот несколько незначительных замечаний по вашему текущему коду:

  • Неправильно использовать 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.reader и csv.writer описано в документации по модулю csv .

В качестве дальнейшего замечания у вас могут быть веские причины для того, чтобы принимать глобус в качестве параметра, а не только файлы в командной строке, ноэто немного удивительно - вам придется называть ваш скрипт как ./whatever.py '*.csv', а не просто ./whatever.py *.csv.Вместо этого вы можете просто сделать:

for filename in sys.argv[1:]:

... и позволить оболочке расширить ваш глобус до того, как скрипт узнает об этом.

И еще одна вещь - текущий подходВзятие является немного опасным, в том случае, если что-то не получится при обратной записи в одно и то же имя файла, вы потеряете данные.Стандартный способ избежать этого - вместо этого записывать во временный файл и, если это было успешно, переименовать временный файл поверх оригинала.Таким образом, вы можете переписать все это как:

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)
1 голос
/ 18 апреля 2011

вы можете использовать fileinput для редактирования на месте

import sys
import glob
import fileinput

for filename in glob.glob(sys.argv[1]):
    for line in fileinput.FileInput(filename,inplace=1) :
       if fileinput.lineno()==1:
          print line.rstrip() + " ID"
       else
          print line.rstrip() + "," + filename
1 голос
/ 18 апреля 2011

Вы можете попробовать изменить свой код, но рекомендуется использовать csv модуль .Это должно дать вам желаемый результат:

import sys
import glob
import csv

filename = glob.glob(sys.argv[1])[0]
yourfile = csv.reader(open(filename, 'rw'))

csv_output=[]

for row in yourfile:
    if len(csv_output) != 0:     # skip the header
        row.append(filename)
    csv_output.append(row)

yourfile = csv.writer(open(filename,'w'),delimiter=',')
yourfile.writerows(csv_output)
1 голос
/ 18 апреля 2011

Используйте модуль CSV , который поставляется с Python.

import csv
import sys

def process_file(filename):
    # Read the contents of the file into a list of lines.
    f = open(filename, 'r')
    contents = f.readlines()
    f.close()

    # Use a CSV reader to parse the contents.
    reader = csv.reader(contents)

    # Open the output and create a CSV writer for it.
    f = open(filename, 'wb')
    writer = csv.writer(f)

    # Process the header.
    header = reader.next()
    header.append('ID')
    writer.writerow(header)

    # Process each row of the body.
    for row in reader:
        row.append(filename)
        writer.writerow(row)

    # Close the file and we're done.
    f.close()

# Run the function on all command-line arguments. Note that this does no
# checking for things such as file existence or permissions.
map(process_file, sys.argv[1:])

Вы можете запустить это следующим образом:

blair@blair-eeepc:~$ python csv_add_filename.py file1.csv file2.csv
1 голос
/ 18 апреля 2011

Вы можете попробовать:

data = [file.readline().rstrip() + ",id"]
data += [line.rstrip() + "," + filename for line in file]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...