Python 2.7 如何读写 CSV 文件的代码

6

我有一个关于Python 2.7读写带有'utf-8-sig'编码的csv文件的问题,我的csv文件标题是:

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

有一些代码("\xef\xbb\xbfID")我从文件A.csv中读取,我希望将相同的代码和标题写入到文件B.csv中。

我的打印日志如下:

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

但实际的输出文件头看起来像是:
ÔªøID;timestamp

这里是代码:

在这里输入图片描述


涉及IT技术的翻译如下,仅供参考:
Here is the code: 这里是代码
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)
2个回答

20

'\xef\xbb\xbf' 是 Unicode 中 ZERO WIDTH NO-BREAK SPACE U+FEFF 的 UTF8 编码版本。它经常被用作字节顺序标记在unicode文本文件的开头:

  • 当你有3个字节: '\xef\xbb\xbf',则文件是utf8编码的
  • 当你有2个字节: '\xff\xfe',则文件是utf16小端编码的
  • 当你有2个字节: '\xfe\xff',则文件是utf16大端编码的

'utf-8-sig' 编码明确要求在文件开头写入此BOM。

要在 Python 2 中自动处理CSV文件的读取时间,您可以使用 codecs 模块:

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

EncodedFile将通过在utf8-sig中对其进行解码来包装原始文件对象,实际上跳过BOM并重新编码为没有BOM的utf8


嗨,Serge,谢谢你的建议,我尝试了,但问题仍然存在。我在想是因为writer.writerow(original_header)而导致问题,因为original_header是一个列表。 - SharpLu
1
顺便问一下,如果出现了 \xef\xbb\xbf\xef\xbb\xbf 这段代码是什么意思? - SharpLu
1
@SharpLu:如果你有两个UTF8 BOM,那么这个文件已经被错误地编码了两次UTF8-SIG。 - Serge Ballesta
谢谢,问题已经解决。 - SharpLu
5
@SergeBallesta,看起来EncodedFile中的参数被颠倒了。应该是这样的吗?codecs.EncodedFile(infile, 'utf-8', 'utf-8-sig') - Allan Spreys
1
我同意@VladSpreys的观点。参数被颠倒了! - ty.

5
您想要使用来自 `codecs` 库的 `EncodedFile` 方法,就像 Serge Ballesta 的回答中一样。
但是在使用 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=";")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接