python: использовать CSV-ридер с одним файлом, извлеченным из tarfile - PullRequest
1 голос
/ 07 апреля 2020

Я пытаюсь использовать Python CSV reader для чтения CSV-файла, который я извлекаю из .tar.gz файла, используя библиотеку tarfile Python .

У меня есть это:

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?)

Как открыть указанный файл (не распаковывая и не открывая файл)?

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

tarfile.extractfile возвращает объект io.BufferedReader, поток байтов, и все же csv.reader ожидает текстовый поток. Вместо этого вы можете использовать io.TextIOWrapper для преобразования потока байтов в текстовый поток:

import io

...

reader = csv.reader(io.TextIOWrapper(tarredCSV, encoding='utf-8'))
0 голосов
/ 07 апреля 2020

Вам необходимо предоставить файлоподобный объект для 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)

В качестве альтернативы возможное решение здесь: Python3 работа с CSV-файлами в tar-файлах будет


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, поскольку каждый файл читается за один шаг.

...