Python, импортирующий файлы .csv в utf-8 или cp1252 - PullRequest
0 голосов
/ 09 октября 2018

Я задал вопрос некоторое время назад о работе с импортом файлов .csv со специальными символами.В то время я был заинтересован в решении 90% дела, но теперь я вернулся к последним 10%.

Это в основном те же настройки, что и раньше:

  1. Много вводафайлы
  2. Все .csv
  3. Новое: Теперь я хочу сохранить специальные символы в некоторых входах.Однако я не могу контролировать формат всех моих входных файлов, поэтому у меня есть набор файлов, которые мне нужно обработать.Моя попытка решения состояла в том, чтобы передать аргумент ключевого слова, когда я хочу сделать другой формат кодировки.

Вот код:

import csv
import unicodecsv
#<Lots of other declarations and initialization>

def _csv_dict(self, file,index_field, ScrubMe, **kwargs):

#some irrelevant initialization stuff here.

    if 'formatting' in kwargs:
        formatting = kwargs['formatting']
    else:
        formatting =  None #cp1252 is OS default

    with open(file, encoding=formatting, errors='ignore') as f: #newline = '',
        if formatting == None:
            reader = csv.DictReader(f, dialect = 'excel')
        else: #assume for now UTF-8 is the only other supported format
            reader = unicodecsv.DictReader(f, dialect = csv.excel)

        for line in reader:
            <do some stuff - it's mostly building dictionaries, but I
generally edit the data to only keep the stuff I care about and do a little
data transformation to standard formats >

Результат вышечто если я передам файл Excel, сохраненный как .CSV в родном кодеке, импорт будет работать.Однако файл unicodecsv с вызовом, включающим ключевое слово formatting = 'utf-8', вызывает ошибку

Сообщение об ошибке указывает на то, что я передаю объект неправильного типа где-то вдоль линии.Это происходит в первый раз, когда я пытаюсь прочитать строку из файла UTF-8

File 
"C:\Users\<me>\AppData\Local\Programs\Python\Python37\lib\site-
packages\unicodecsv\py3.py", line 51, in <genexpr>
f = (bs.decode(encoding, errors=errors) for bs in f)
AttributeError: 'str' object has no attribute 'decode'

Из того, что я прочитал, UTF-8 на самом деле отделяется табуляцией вместо запятой, но я "Я думаю, что это должно работать так же.

Мне кажется, что я, возможно, испортил что-то довольно простое, но я убил достаточно времени, глядя на то, что кажется уместным обратиться за помощью.Заранее спасибо за любые предложения.

1 Ответ

0 голосов
/ 09 октября 2018

Я заменяю свой первоначальный ответ, потому что у меня было несколько вещей, и мне потребовалось некоторое время, чтобы распутать их.

1) @lenz правильно.В Python 3 нет необходимости использовать unicodecsv.DictReader.Часть того, что меня смутило, - это разница в реализации.

a) Для более старого unicodecsv.DictReader от Python 2:

kw_args={'errors' : None}
with open(filename, 'rb', **kw_args) as file:
    reader = unicodecsv.DictReader(file, dialect = csv.excel, encoding='utf_8_sig' )

b) Для Python 3 csv.DictReader

kw_args={'newline' : '','errors' : None,'encoding' : 'utf_8_sig'}
with open(filename, 'r', **kw_args) as file:
    reader = csv.DictReader(file, dialect = csv.excel )

Суммируя различия

  • Режим открытия файла теперь текстовый, а не байты
  • Из-за другого метода открытия кодек можно / нужно указывать вСравнение открытия файла в DictReader
  • Параметр новой строки также действителен только для файла, открытого в виде текста.

2) Поскольку мой файл UTF-8 был создан в Excel, он имеетспецификация в стиле utf_16_le вверху файла.Единственный код, который работает для этого, - utf_8_sig.

3) Поскольку мои выходные файлы читаются нисходящим потоком SQL Server, выходной кодек должен быть 'utf_16_le', иначе SQL Server его не распознает.

4) Кроме того, посколькуцель - SQL Server, мне нужно вручную вставить спецификацию вверху файла.

csvfile.write('\uFEFF') 
writer.writeheader()

Если вы откроете вышеуказанный выходной файл в Excel, он больше не будет в столбцах, а будет SQL Server (на самом делеСлужба SSIS) теперь знает, как читать файл.

5) Просто, чтобы поболтать со мной немного, у кого-то было \ n в нескольких записях.С Excel в качестве источника и назначения это не было проблемой, но это было для SSIS.Мое решение:

for r in record_list:
    temp={}
    for k,v in r.items():

        if isinstance(v,str):
            temp[k] = v.replace('\n',' ')
        else:
            temp[k] = v
    writer.writerow(temp) 
...