Рубрики
Без рубрики

CSV – Comma-разделенные значения значений

Автор оригинала: Doug Hellmann.

Цель:

Читайте и напишите файлы разделенных запятой.

Модуль CSV может использоваться для работы с данными, экспортированными из таблиц, и баз данных в текстовые файлы, отформатированные с полями и записями, обычно называемыми как Comma, разделенные запятыми. Поскольку запятые часто используются для разделения полей в записи.

Чтение

Используйте READER () , чтобы создать объект для чтения данных из файла CSV. Читатель может использоваться в качестве итератора для обработки строк файла в порядке. Например

csv_reader.py

import csv
import sys

with open(sys.argv[1], 'rt') as f:
    reader  csv.reader(f)
    for row in reader:
        print(row)

Первый аргумент Reader () является источником текстовых строк. В этом случае это файл, но любое намерение принимается (<код> Stringio экземпляр <код> и т. Д.). Другие дополнительные аргументы могут быть предоставлены для контроля, как анализируются входные данные.

"Title 1","Title 2","Title 3","Title 4"
1,"a",08/18/07,"å"
2,"b",08/19/07,"∫"
3,"c",08/20/07,"ç"

Как читается, каждая строка входных данных проанализирована и преобразована в список <код> строк.

$ python3 csv_reader.py testdata.csv

['Title 1', 'Title 2', 'Title 3', 'Title 4']
['1', 'a', '08/18/07', 'å']
['2', 'b', '08/19/07', '∫']
['3', 'c', '08/20/07', 'ç']

Разрушивает разрывов анализатора, встроенные внутри строк в строке, поэтому «ряд» не всегда такой же, как «строка» ввода из файла.

"Title 1","Title 2","Title 3"
1,"first line
second line",08/18/07

Поля с перерывами линии на входном состоянии сохраняют внутреннюю линию, когда они возвращаются парсером.

$ python3 csv_reader.py testlinebreak.csv

['Title 1', 'Title 2', 'Title 3']
['1', 'first line\nsecond line', '08/18/07']

Письмо

Написание файлов CSV так же просто, как их читают. Используйте WRISTER () Чтобы создать объект для записи, затем повторяйте по ряду, используя WRITERWOW () , чтобы распечатать их.

csv_writer.py

import csv
import sys

unicode_chars  'å∫ç'

with open(sys.argv[1], 'wt') as f:
    writer  csv.writer(f)
    writer.writerow(('Title 1', 'Title 2', 'Title 3', 'Title 4'))
    for i in range(3):
        row  (
            i + 1,
            chr(ord('a') + i),
            '08/{:02d}/07'.format(i + 1),
            unicode_chars[i],
        )
        writer.writerow(row)

print(open(sys.argv[1], 'rt').read())

Выход не выглядит точно так же, как экспортируемые данные, используемые в примере читателя, потому что ему не хватает цитат вокруг некоторых значений.

$ python3 csv_writer.py testout.csv

Title 1,Title 2,Title 3,Title 4
1,a,08/01/07,å
2,b,08/02/07,∫
3,c,08/03/07,ç

Цитирование

По умолчанию по умолчанию поведение отличается для писателя, поэтому вторые и третий столбцы в предыдущем примере не указаны. Чтобы добавить цитаты, установите AQUIRY ARGITY на одну из других мод цитирования.

writer = csv.writer(f,

В этом случае QUOTE_NONNUNUMIC добавляет цитаты вокруг всех столбцов, которые содержат значения, которые не являются номерами.

$ python3 csv_writer_quoted.py testout_quoted.csv

"Title 1","Title 2","Title 3","Title 4"
1,"a","08/01/07","å"
2,"b","08/02/07","∫"
3,"c","08/03/07","ç"

Существует четыре разных варианта цитирования, определяемые как константы в модуле CSV.

Quote_all.

Процитировать все, независимо от типа.

Quote_minimal.

Цитировать поля со специальными символами (что угодно, что путает парсер настроен с тем же диалектом и параметрами). Это по умолчанию

QUOTE_NONNUMERIC

Цитата всех полей, которые не являются целыми числами или поплавками. При использовании с читателем, Входные поля, которые не указаны, преобразуются в плавать.

Quote_none.

Не процитируйте что-нибудь на выходе. При использовании с читателем, цитаты включены в значения поля (обычно, они рассматриваются как разделители и раздевается).

Диалекты

Нет четко определенного стандарта для файлов значения Comma Comma, поэтому анализатор должен быть гибким. Эта гибкость означает, что есть много параметров для управления, как CSV разбирается или записывает данные. Вместо того, чтобы проходить каждый из этих параметров для читателя и писателя отдельно, они сгруппированы вместе в диалект .

Классы диалектов могут быть зарегистрированы по имени, поэтому абоненты CSV Module не должны заранее знать параметры настроек. Полный список зарегистрированных диалектов может быть получен с помощью LIST_DIALECTS () .

csv_list_dialects.py

import csv

print(csv.list_dialects())

Стандартная библиотека включает в себя три диалекты: Excel , <код> вкладки Excel и <код> UNIX . Excel Dialect предназначен для работы с данными в формате экспорта по умолчанию для Microsoft Excel, а также работает с libreOffice . UNIX диалект цитаты всех полей двумя цитатами и использует <код> \ N в качестве сепаратора записи.

$ python3 csv_list_dialects.py

['excel', 'excel-tab', 'unix']

Создание диалекта

Если вместо того, чтобы использовать запятые, чтобы разделить поля, входной файл использует трубы (<код> | ), как это

"Title 1"|"Title 2"|"Title 3"
1|"first line
second line"|08/18/07

Новый диалект может быть зарегистрирован с использованием соответствующего разделителя.

csv_dialect.py

import csv

csv.register_dialect('pipes', delimiter'|')

with open('testdata.pipes', 'r') as f:
    reader  csv.reader(f, dialect'pipes')
    for row in reader:
        print(row)

Используя диалект «Трубы», файл можно прочитать так же, как с помощью файла Comma-Delimited.

$ python3 csv_dialect.py

['Title 1', 'Title 2', 'Title 3']
['1', 'first line\nsecond line', '08/18/07']

Параметры диалекта

Диалект указывает все токены, используемые при анализе или записи файла данных. В приведенной ниже таблице перечислены аспекты формата файла, который можно указать, от того, как столбец разграничиваются к символу, используемую для выхода из токена.

Параметры диалекта CSV

Атрибут

Дефолт

Смысл

делимитр

Полевой сепаратор (один символ)

сюжета

Истинный

Флаг контролирует, будут ли экземпляры QotoChar

escapechar.

Никто

Символ используется для обозначения последовательности побега

Лентерминатор

\ r \ n

Строка, используемая писателем для завершения строки

договор

Строка в поля объемного звучания, содержащие специальные значения (один символ)

цитирование

Quote_minimal.

Контроль цитирования поведения описано ранее

Skipinitialspace.

Ложь

Игнорировать пробел после разделителя поля

csv_dialect_variations.py

import csv
import sys

csv.register_dialect('escaped',
                     escapechar'\\',
                     doublequoteFalse,
                     quotingcsv.QUOTE_NONE,
                     )
csv.register_dialect('singlequote',
                     quotechar"'",
                     quotingcsv.QUOTE_ALL,
                     )

quoting_modes  {
    getattr(csv, n): n
    for n in dir(csv)
    if n.startswith('QUOTE_')
}

TEMPLATE  '''\
Dialect: "{name}"

  delimiter   = {dl!r:<6}    skipinitialspace = {si!r}
  doublequote = {dq!r:<6}    quoting          = {qu}
  quotechar   = {qc!r:<6}    lineterminator   = {lt!r}
  escapechar  = {ec!r:<6}
'''

for name in sorted(csv.list_dialects()):
    dialect  csv.get_dialect(name)

    print(TEMPLATE.format(
        namename,
        dldialect.delimiter,
        sidialect.skipinitialspace,
        dqdialect.doublequote,
        ququoting_modes[dialect.quoting],
        qcdialect.quotechar,
        ltdialect.lineterminator,
        ecdialect.escapechar,
    ))

    writer  csv.writer(sys.stdout, dialectdialect)
    writer.writerow(
        ('col1', 1, '10/01/2010',
         'Special chars: " \' {} to parse'.format(
             dialect.delimiter))
    )
    print()

Эта программа показывает, как появляется те же данные при отформатировании с использованием нескольких различных диалектов.

$ python3 csv_dialect_variations.py

Dialect: "escaped"

  delimiter   = ','       skipinitialspace = 0
  doublequote = 0         quoting          = QUOTE_NONE
  quotechar   = '"'       lineterminator   = '\r\n'
  escapechar  = '\\'

col1,1,10/01/2010,Special chars: \" ' \, to parse

Dialect: "excel"

  delimiter   = ','       skipinitialspace = 0
  doublequote = 1         quoting          = QUOTE_MINIMAL
  quotechar   = '"'       lineterminator   = '\r\n'
  escapechar  = None

col1,1,10/01/2010,"Special chars: "" ' , to parse"

Dialect: "excel-tab"

  delimiter   = '\t'      skipinitialspace = 0
  doublequote = 1         quoting          = QUOTE_MINIMAL
  quotechar   = '"'       lineterminator   = '\r\n'
  escapechar  = None

col1    1       10/01/2010      "Special chars: "" '     to parse"

Dialect: "singlequote"

  delimiter   = ','       skipinitialspace = 0
  doublequote = 1         quoting          = QUOTE_ALL
  quotechar   = "'"       lineterminator   = '\r\n'
  escapechar  = None

'col1','1','10/01/2010','Special chars: " '' , to parse'

Dialect: "unix"

  delimiter   = ','       skipinitialspace = 0
  doublequote = 1         quoting          = QUOTE_ALL
  quotechar   = '"'       lineterminator   = '\n'
  escapechar  = None

"col1","1","10/01/2010","Special chars: "" ' , to parse"

Автоматически обнаруживать диалекты

Лучший способ настроить диалект для анализа входного файла – это заранее узнать правильные настройки. Для данных, когда параметры диалекта неизвестны, Sniffer Class можно использовать для получения образованного догада. Метод SNIFF () принимает образец входных данных и дополнительный аргумент, обеспечивающий возможные символы разделителя.

csv_dialect_sniffer.py

import csv
from io import StringIO
import textwrap

csv.register_dialect('escaped',
                     escapechar'\\',
                     doublequoteFalse,
                     quotingcsv.QUOTE_NONE)
csv.register_dialect('singlequote',
                     quotechar"'",
                     quotingcsv.QUOTE_ALL)

# Generate sample data for all known dialects
samples  []
for name in sorted(csv.list_dialects()):
    buffer  StringIO()
    dialect  csv.get_dialect(name)
    writer  csv.writer(buffer, dialectdialect)
    writer.writerow(
        ('col1', 1, '10/01/2010',
         'Special chars " \' {} to parse'.format(
             dialect.delimiter))
    )
    samples.append((name, dialect, buffer.getvalue()))

# Guess the dialect for a given sample, and then use the results
# to parse the data.
sniffer  csv.Sniffer()
for name, expected, sample in samples:
    print('Dialect: "{}"'.format(name))
    print('In: {}'.format(sample.rstrip()))
    dialect  sniffer.sniff(sample, delimiters',\t')
    reader  csv.reader(StringIO(sample), dialectdialect)
    print('Parsed:\n  {}\n'.format(
          '\n  '.join(repr(r) for r in next(reader))))

<Код> нюхает () Возвращает диалект с настройками, которые будут использоваться для анализа данных. Результаты не всегда идеальны, как продемонстрировано «сбежавшим» диалектом в примере.

$ python3 csv_dialect_sniffer.py

Dialect: "escaped"
In: col1,1,10/01/2010,Special chars \" ' \, to parse
Parsed:
  'col1'
  '1'
  '10/01/2010'
  'Special chars \\" \' \\'
  ' to parse'

Dialect: "excel"
In: col1,1,10/01/2010,"Special chars "" ' , to parse"
Parsed:
  'col1'
  '1'
  '10/01/2010'
  'Special chars " \' , to parse'

Dialect: "excel-tab"
In: col1        1       10/01/2010      "Special chars "" '      to parse"
Parsed:
  'col1'
  '1'
  '10/01/2010'
  'Special chars " \' \t to parse'

Dialect: "singlequote"
In: 'col1','1','10/01/2010','Special chars " '' , to parse'
Parsed:
  'col1'
  '1'
  '10/01/2010'
  'Special chars " \' , to parse'

Dialect: "unix"
In: "col1","1","10/01/2010","Special chars "" ' , to parse"
Parsed:
  'col1'
  '1'
  '10/01/2010'
  'Special chars " \' , to parse'

Используя полевые имена

В дополнение к работе с последовательностями данных, модуль CSV включает в себя классы для работы со строками в качестве словарей, чтобы поля были названы. <Код> Dictreader и <код> dictwriter классы переводят строки в словари вместо списков. Клавиши для словаря могут быть переданы или выведены из первой строки на входе (когда строка содержит заголовки).

csv_dictreader.py

import csv
import sys

with open(sys.argv[1], 'rt') as f:
    reader  csv.DictReader(f)
    for row in reader:
        print(row)

Словарь на основе читателя и писателя реализуются как обертки вокруг классов на основе последовательности, и используют те же методы и аргументы. Единственное различие в API Reader заключается в том, что строки возвращаются в виде экземпляров упорядоченности вместо списков или кортежей (под более ранним значением Python, строки были возвращены как обычные Dict экземпляров).

$ python3 csv_dictreader.py testdata.csv

OrderedDict([('Title 1', '1'), ('Title 2', 'a'), ('Title 3',
'08/18/07'), ('Title 4', 'å')])
OrderedDict([('Title 1', '2'), ('Title 2', 'b'), ('Title 3',
'08/19/07'), ('Title 4', '∫')])
OrderedDict([('Title 1', '3'), ('Title 2', 'c'), ('Title 3',
'08/20/07'), ('Title 4', 'ç')])

<Код> DictWriter должен быть предоставлен список имен полей, чтобы он знал, как заказать столбцы в выходе.

csv_dictwriter.py

import csv
import sys

fieldnames  ('Title 1', 'Title 2', 'Title 3', 'Title 4')
headers  {
    n: n
    for n in fieldnames
}
unicode_chars  'å∫ç'

with open(sys.argv[1], 'wt') as f:

    writer  csv.DictWriter(f, fieldnamesfieldnames)
    writer.writeheader()

    for i in range(3):
        writer.writerow({
            'Title 1': i + 1,
            'Title 2': chr(ord('a') + i),
            'Title 3': '08/{:02d}/07'.format(i + 1),
            'Title 4': unicode_chars[i],
        })

print(open(sys.argv[1], 'rt').read())

Имена поля не записываются в файл автоматически, но их можно написать явно с помощью метода Code> INCORDELEDER () .

$ python3 csv_dictwriter.py testout.csv

Title 1,Title 2,Title 3,Title 4
1,a,08/01/07,å
2,b,08/02/07,∫
3,c,08/03/07,ç

Смотрите также