Python загрузить csv файл
Одним из распространенных файловых форматов, которые хранят в удобном виде информацию, является формат csv . Каждая строка в файле csv представляет отдельную запись или строку, которая состоит из отдельных столбцов, разделенных запятыми. Собственно поэтому формат и называется Comma Separated Values. Но хотя формат csv — это формат текстовых файлов, Python для упрощения работы с ним предоставляет специальный встроенный модуль csv .
Рассмотрим работу модуля на примере:
import csv FILENAME = "users.csv" users = [ ["Tom", 28], ["Alice", 23], ["Bob", 34] ] with open(FILENAME, "w", newline="") as file: writer = csv.writer(file) writer.writerows(users) with open(FILENAME, "a", newline="") as file: user = ["Sam", 31] writer = csv.writer(file) writer.writerow(user)
В файл записывается двухмерный список — фактически таблица, где каждая строка представляет одного пользователя. А каждый пользователь содержит два поля — имя и возраст. То есть фактически таблица из трех строк и двух столбцов.
При открытии файла на запись в качестве третьего параметра указывается значение newline=»» — пустая строка позволяет корректно считывать строки из файла вне зависимости от операционной системы.
Для записи нам надо получить объект writer , который возвращается функцией csv.writer(file) . В эту функцию передается открытый файл. А собственно запись производится с помощью метода writer.writerows(users) Этот метод принимает набор строк. В нашем случае это двухмерный список.
Если необходимо добавить одну запись, которая представляет собой одномерный список, например, [«Sam», 31] , то в этом случае можно вызвать метод writer.writerow(user)
В итоге после выполнения скрипта в той же папке окажется файл users.csv, который будет иметь следующее содержимое:
Tom,28 Alice,23 Bob,34 Sam,31
Для чтения из файла нам наоборот нужно создать объект reader :
import csv FILENAME = "users.csv" with open(FILENAME, "r", newline="") as file: reader = csv.reader(file) for row in reader: print(row[0], " - ", row[1])
При получении объекта reader мы можем в цикле перебрать все его строки:
Tom - 28 Alice - 23 Bob - 34 Sam - 31
Работа со словарями
В примере выше каждая запись или строка представляла собой отдельный список, например, [«Sam», 31] . Но кроме того, модуль csv имеет специальные дополнительные возможности для работы со словарями. В частности, функция csv.DictWriter() возвращает объект writer, который позволяет записывать в файл. А функция csv.DictReader() возвращает объект reader для чтения из файла. Например:
import csv FILENAME = "users.csv" users = [ , , ] with open(FILENAME, "w", newline="") as file: columns = ["name", "age"] writer = csv.DictWriter(file, fieldnames=columns) writer.writeheader() # запись нескольких строк writer.writerows(users) user = # запись одной строки writer.writerow(user) with open(FILENAME, "r", newline="") as file: reader = csv.DictReader(file) for row in reader: print(row["name"], "-", row["age"])
Запись строк также производится с помощью методов writerow() и writerows() . Но теперь каждая строка представляет собой отдельный словарь, и кроме того, производится запись и заголовков столбцов с помощью метода writeheader() , а в метод csv.DictWriter в качестве второго параметра передается набор столбцов.
При чтении строк, используя названия столбцов, мы можем обратиться к отдельным значениям внутри строки: row[«name»] .
Работа с файлами в формате CSV#
CSV (comma-separated value) — это формат представления табличных данных (например, это могут быть данные из таблицы или данные из БД).
В этом формате каждая строка файла — это строка таблицы. Несмотря на название формата, разделителем может быть не только запятая.
И хотя у форматов с другим разделителем может быть и собственное название, например, TSV (tab separated values), тем не менее, под форматом CSV понимают, как правило, любые разделители.
Пример файла в формате CSV (sw_data.csv):
hostname,vendor,model,location sw1,Cisco,3750,London sw2,Cisco,3850,Liverpool sw3,Cisco,3650,Liverpool sw4,Cisco,3650,London
В стандартной библиотеке Python есть модуль csv, который позволяет работать с файлами в CSV формате.
Чтение#
Пример чтения файла в формате CSV (файл csv_read.py):
import csv with open('sw_data.csv') as f: reader = csv.reader(f) for row in reader: print(row)
$ python csv_read.py ['hostname', 'vendor', 'model', 'location'] ['sw1', 'Cisco', '3750', 'London'] ['sw2', 'Cisco', '3850', 'Liverpool'] ['sw3', 'Cisco', '3650', 'Liverpool'] ['sw4', 'Cisco', '3650', 'London']
В первом списке находятся названия столбцов, а в остальных соответствующие значения.
Обратите внимание, что сам csv.reader возвращает итератор:
In [1]: import csv In [2]: with open('sw_data.csv') as f: . : reader = csv.reader(f) . : print(reader) . : _csv.reader object at 0x10385b050>
При необходимости его можно превратить в список таким образом:
In [3]: with open('sw_data.csv') as f: . : reader = csv.reader(f) . : print(list(reader)) . : [['hostname', 'vendor', 'model', 'location'], ['sw1', 'Cisco', '3750', 'London'], ['sw2', 'Cisco', '3850', 'Liverpool'], ['sw3', 'Cisco', '3650', 'Liverpool'], ['sw4', 'Cisco', '3650', 'London']]
Чаще всего заголовки столбцов удобней получить отдельным объектом. Это можно сделать таким образом (файл csv_read_headers.py):
import csv with open('sw_data.csv') as f: reader = csv.reader(f) headers = next(reader) print('Headers: ', headers) for row in reader: print(row)
Иногда в результате обработки гораздо удобней получить словари, в которых ключи — это названия столбцов, а значения — значения столбцов.
Для этого в модуле есть DictReader (файл csv_read_dict.py):
import csv with open('sw_data.csv') as f: reader = csv.DictReader(f) for row in reader: print(row) print(row['hostname'], row['model'])
$ python csv_read_dict.py sw1 3750 sw2 3850 sw3 3650 sw4 3650
До Python 3.8 возвращался отдельный тип упорядоченные словари (OrderedDict).
Запись#
Аналогичным образом с помощью модуля csv можно и записать файл в формате CSV (файл csv_write.py):
import csv data = [['hostname', 'vendor', 'model', 'location'], ['sw1', 'Cisco', '3750', 'London, Best str'], ['sw2', 'Cisco', '3850', 'Liverpool, Better str'], ['sw3', 'Cisco', '3650', 'Liverpool, Better str'], ['sw4', 'Cisco', '3650', 'London, Best str']] with open('sw_data_new.csv', 'w') as f: writer = csv.writer(f) for row in data: writer.writerow(row) with open('sw_data_new.csv') as f: print(f.read())
В примере выше строки из списка сначала записываются в файл, а затем содержимое файла выводится на стандартный поток вывода.
$ python csv_write.py hostname,vendor,model,location sw1,Cisco,3750,"London, Best str" sw2,Cisco,3850,"Liverpool, Better str" sw3,Cisco,3650,"Liverpool, Better str" sw4,Cisco,3650,"London, Best str"
Обратите внимание на интересную особенность: строки в последнем столбце взяты в кавычки, а остальные значения — нет.
Так получилось из-за того, что во всех строках последнего столбца есть запятая. И кавычки указывают на то, что именно является целой строкой. Когда запятая находится в кавычках, модуль csv не воспринимает её как разделитель.
Иногда лучше, чтобы все строки были в кавычках. Конечно, в данном случае достаточно простой пример, но когда в строках больше значений, то кавычки позволяют указать, где начинается и заканчивается значение.
Модуль csv позволяет управлять этим. Для того, чтобы все строки записывались в CSV-файл с кавычками, надо изменить скрипт таким образом (файл csv_write_quoting.py):
import csv data = [['hostname', 'vendor', 'model', 'location'], ['sw1', 'Cisco', '3750', 'London, Best str'], ['sw2', 'Cisco', '3850', 'Liverpool, Better str'], ['sw3', 'Cisco', '3650', 'Liverpool, Better str'], ['sw4', 'Cisco', '3650', 'London, Best str']] with open('sw_data_new.csv', 'w') as f: writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC) for row in data: writer.writerow(row) with open('sw_data_new.csv') as f: print(f.read())
$ python csv_write_quoting.py "hostname","vendor","model","location" "sw1","Cisco","3750","London, Best str" "sw2","Cisco","3850","Liverpool, Better str" "sw3","Cisco","3650","Liverpool, Better str" "sw4","Cisco","3650","London, Best str"
Теперь все значения с кавычками. И поскольку номер модели задан как строка в изначальном списке, тут он тоже в кавычках.
Кроме метода writerow, поддерживается метод writerows. Ему можно передать любой итерируемый объект.
Например, предыдущий пример можно записать таким образом (файл csv_writerows.py):
import csv data = [['hostname', 'vendor', 'model', 'location'], ['sw1', 'Cisco', '3750', 'London, Best str'], ['sw2', 'Cisco', '3850', 'Liverpool, Better str'], ['sw3', 'Cisco', '3650', 'Liverpool, Better str'], ['sw4', 'Cisco', '3650', 'London, Best str']] with open('sw_data_new.csv', 'w') as f: writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC) writer.writerows(data) with open('sw_data_new.csv') as f: print(f.read())
DictWriter#
С помощью DictWriter можно записать словари в формат CSV.
В целом DictWriter работает так же, как writer, но так как словари не упорядочены, надо указывать явно в каком порядке будут идти столбцы в файле. Для этого используется параметр fieldnames (файл csv_write_dict.py):
import csv data = [ 'hostname': 'sw1', 'location': 'London', 'model': '3750', 'vendor': 'Cisco' >, 'hostname': 'sw2', 'location': 'Liverpool', 'model': '3850', 'vendor': 'Cisco' >, 'hostname': 'sw3', 'location': 'Liverpool', 'model': '3650', 'vendor': 'Cisco' >, 'hostname': 'sw4', 'location': 'London', 'model': '3650', 'vendor': 'Cisco' >] with open('csv_write_dictwriter.csv', 'w') as f: writer = csv.DictWriter( f, fieldnames=list(data[0].keys()), quoting=csv.QUOTE_NONNUMERIC) writer.writeheader() for d in data: writer.writerow(d)
Указание разделителя#
Иногда в качестве разделителя используются другие значения. В таком случае должна быть возможность подсказать модулю, какой именно разделитель использовать.
Например, если в файле используется разделитель ; (файл sw_data2.csv):
hostname;vendor;model;location sw1;Cisco;3750;London sw2;Cisco;3850;Liverpool sw3;Cisco;3650;Liverpool sw4;Cisco;3650;London
Достаточно просто указать, какой разделитель используется в reader (файл csv_read_delimiter.py):
import csv with open('sw_data2.csv') as f: reader = csv.reader(f, delimiter=';') for row in reader: print(row)