python:使用 CSV reader 从 tarfile 中提取单个文件

python: use CSV reader with single file extracted from tarfile

我正在尝试使用 Python CSV reader to read a CSV file that I extract from a .tar.gz file using Python's tarfile library

我有这个:

tarFile = tarfile.open(name=tarFileName, mode="r")
for file in tarFile.getmembers():
    tarredCSV = tarFile.extractfile(file)
    reader = csv.reader(tarredCSV)
    next(reader)    # skip header
    for row in reader:
        if row[3] not in CSVRows.values():
            CSVRows[row[3]] = row

tar文件中的所有文件都是CSV。

第一个文件出现异常。我在第一 next 行收到此异常:

_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

如何打开上述文件(不解压文件然后打开)?

tarfile.extractfile returns 一个 io.BufferedReader 对象,一个字节流,但 csv.reader 需要一个文本流。您可以使用 io.TextIOWrapper 将字节流转换为文本流:

import io

...

reader = csv.reader(io.TextIOWrapper(tarredCSV, encoding='utf-8'))

您需要向 csv.reader 提供一个类似文件的对象。

可能最好的解决方案是这种方法(感谢 blhsing 和 damon 的建议):

import csv
import io
import tarfile

tarFile = tarfile.open(name=tarFileName, mode="r")
for file in tarFile.getmembers():
    csv_file = io.TextIOWrapper(tarFile.extractfile(file), encoding="utf-8")

    reader = csv.reader(csv_file)
    next(reader)    # skip header
    for row in reader:
        print(row)

或者这里的一个可能的解决方案: 将是


import csv
import io
import tarfile

tarFile = tarfile.open(name=tarFileName, mode="r")
for file in tarFile.getmembers():
    csv_file = io.StringIO(tarFile.extractfile(file).read().decode('utf-8'))

    reader = csv.reader(csv_file)
    next(reader)    # skip header
    for row in reader:
        print(row)

这里有一个io.StringIO对象用来让csv.reader开心。但是,对于 tar 中包含的较大文件,这可能无法很好地扩展,因为每个文件都是一步读取的。