Файл CSV Python 2.7 для чтения/записи \xef\xbb\xbf code

У меня есть вопрос о CSV-файле Python 2.7 для чтения/записи с кодом «utf-8-sig», мой csv . заголовок

['\xef\xbb\xbfID;timestamp;CustomerID;Email']

есть некоторый код ("\xef\xbb\xbfID"), который я читаю из файла A.csv, и я хочу записать тот же код и заголовок в файл B.csv

Мой журнал печати показывает:

['\xef\xbb\xbfID;timestamp;CustomerID;Email']

Но фактический заголовок выходного файла выглядит так

ÔªøID;timestamp

введите описание изображения здесь

Вот код:

def remove_gdpr_info_from_csv(file_path, file_name, temp_folder, original_header):
    new_temp_folder = tempfile.mkdtemp()
    new_temp_file = new_temp_folder + "/" + file_name
    # Blanked new file
    with open(new_temp_file, 'wb') as outfile:
        writer = csv.writer(outfile, delimiter=";")
        print original_header
        writer.writerow(original_header)
        # File from SFTP
        with open(file_path, 'r') as infile:
            reader = csv.reader(infile, delimiter=";")
            first_row = next(reader)
            email = first_row.index('Email')
            contract_detractor1 = first_row.index('Contact Detractor (Q21)')
            contract_detractor2 = first_row.index('Contact Detractor (Q20)')
            contract_detractor3 = first_row.index('Contact Detractor (Q43)')
            contract_detractor4 = first_row.index('Contact Detractor(Q26)')
            contract_detractor5 = first_row.index('Contact Detractor(Q27)')
            contract_detractor6 = first_row.index('Contact Detractor(Q44)')
            indexes = []
            for column_name in header_list:
                ind = first_row.index(column_name)
                indexes.append(ind)

            for row in reader:
                output_row = []
                for ind in indexes:
                    data = row[ind]
                    if ind == email:
                        data = ''
                    elif ind == contract_detractor1:
                        data = ''
                    elif ind == contract_detractor2:
                        data = ''
                    elif ind == contract_detractor3:
                        data = ''
                    elif ind == contract_detractor4:
                        data = ''
                    elif ind == contract_detractor5:
                        data = ''
                    elif ind == contract_detractor6:
                        data = ''
                    output_row.append(data)
                writer.writerow(output_row)
    s3core.upload_files(SPARKY_S3, DESTINATION_PATH, new_temp_file)
    shutil.rmtree(temp_folder)
    shutil.rmtree(new_temp_folder)

person SharpLu    schedule 02.05.2018    source источник


Ответы (2)


'\xef\xbb\xbf' — это кодированная UTF8 версия юникода ZERO WIDTH NO-BREAK SPACE U+FEFF. Он часто используется в качестве метки порядка байтов в начале текстовых файлов Unicode:

  • когда у вас 3 байта: '\xef\xbb\xbf', то файл в кодировке utf8
  • когда у вас есть 2 байта: '\xff\xfe', тогда файл находится в формате utf16 с прямым порядком байтов
  • когда у вас есть 2 байта: '\xfe\xff', тогда файл находится в формате utf16 с прямым порядком байтов

Кодировка 'utf-8-sig' явно запрашивает запись этой спецификации в начале файла.

Чтобы обрабатывать его автоматически во время чтения CSV-файла в Python 2, вы можете использовать модуль codecs:

with open(file_path, 'r') as infile:
    reader = csv.reader(codecs.EncodedFile(infile, 'utf8-sig', 'utf8'), delimiter=";")

EncodedFile завершит исходный файловый объект, декодируя его в utf8-sig, фактически пропуская спецификацию и перекодируя ее в utf8 без спецификации.

person Serge Ballesta    schedule 02.05.2018
comment
Привет Серж, спасибо за предложение, я попробовал, проблема все та же. Мне было интересно, не в этом ли проблема, потому что author.writerow(original_header), original_header — это список. - person SharpLu; 02.05.2018
comment
Кстати если есть \xef\xbb\xbf\xef\xbb\xbf какой это код? - person SharpLu; 02.05.2018
comment
@SharpLu: если у вас вдвое больше спецификации utf8, значит, файл был дважды ошибочно закодирован в utf8-sig. - person Serge Ballesta; 02.05.2018
comment
Спасибо, проблема исправлена. - person SharpLu; 02.05.2018
comment
@SergeBallesta, похоже, аргументы в EncodedFile поменялись местами. Должно ли быть так? codecs.EncodedFile(infile, 'utf-8', 'utf-8-sig')? - person Vlad Spreys; 17.09.2018
comment
Я согласен с @VladSpreys. Аргументы перевернуты! - person ty.; 28.01.2019

Вы хотите использовать метод EncodedFile из библиотеки codecs, как в ответе Сержа Бальесты.

Однако при использовании Python 2.7 кодировка utf-8-sig не является поддерживаемым псевдонимом для кодировки UTF8-sig, вам необходимо использовать utf_8_sig. Кроме того, порядок свойств метода должен определять сначала кодировку выходных данных, а затем кодировку файла: codecs.EncodedFile(file,datacodec,filecodec=None,errors=’strict')

Вот полный результат:

import codecs
with open(file_path, 'r') as infile:
    reader = csv.reader(codecs.EncodedFile(infile, 'utf8', 'utf_8_sig'), delimiter=";")
person Rich Farren    schedule 06.03.2019