【问题标题】:Using csvreader against a gzipped file in Python在 Python 中对 gzipped 文件使用 csvreader
【发布时间】:2012-03-04 09:35:49
【问题描述】:

我有一堆压缩后的 CSV 文件,我想使用 Python 的内置 CSV 阅读器打开这些文件进行检查。我想这样做,而不必先手动将它们解压缩到磁盘。我想我想以某种方式获取未压缩数据的流,并将其传递给 CSV 阅读器。这在 Python 中可行吗?

【问题讨论】:

  • 除了这里的原生 Python 解决方案,pandas 包还有 read_csv 支持 gzip 的阅读器

标签: python csv gzip


【解决方案1】:

使用gzip 模块:

with gzip.open(filename, mode='rt') as f:
    reader = csv.reader(f)
    #...

【讨论】:

  • 如果filename='tzaman.csv',那么它的文件tzaman.csv是一个存档文件,并包含另一个文件tzaman.csv,它实际上是一个csv文件。如果我们将其命名为abc.zip,那么它会添加abc.zip,它是一个zip,并包含一个文件abc.zip,它实际上是一个csv。怎么办?
  • 不压缩文件吗?
  • 它不会创建存档。 Gzip 只是一个流压缩器。文件名应称为“tzsman.csv.gz”以帮助识别文件类型。此外,gzip 库不支持 Python 2.6.8 中的 with 语句。
  • @smci 感谢您的提示。快进 3 1/2 年,我只使用 Python 3.6,除非我必须访问像 yum 这样的旧 API。 contextlib 确实提供了一些漂亮的装饰器。
  • @mazs 您可以在gzip.open 调用中指定文件模式。
【解决方案2】:

我已尝试使用上述版本进行读写,但由于“字节”错误,它在 Python 3.3 中不起作用。然而,经过一些试验和错误,我可以得到以下工作。也许它也对其他人有所帮助:

import csv
import gzip
import io


with gzip.open("test.gz", "w") as file:
    writer = csv.writer(io.TextIOWrapper(file, newline="", write_through=True))
    writer.writerow([1, 2, 3])
    writer.writerow([4, 5, 6])

with gzip.open("test.gz", "r") as file:
    reader = csv.reader(io.TextIOWrapper(file, newline=""))
    print(list(reader))

正如 amohr 所建议的,以下方法也有效:

import gzip, csv

with gzip.open("test.gz", "wt", newline="") as file:
    writer = csv.writer(file)
    writer.writerow([1, 2, 3])
    writer.writerow([4, 5, 6])

with gzip.open("test.gz", "rt", newline="") as file:
    reader = csv.reader(file)
    print(list(reader))

【讨论】:

  • 此解决方案也适用于io.BufferedReader,根据某些benchmarks 可能更快。只需将gzip.openio.BufferedReader 包装成with io.BufferedReader(gzip.open("test.gz", 'r')) as file:
  • 如果你使用 gzip.open(mode='rt',你可以跳过 TextIOWrapper/BufferedReader
  • 这很有用。我只是遇到了一个问题。我所拥有的是 tsv 压缩文件。那是制表符分隔的文件,而不是逗号分隔的文件。如何将制表符转换为逗号?
  • 你可能可以使用csv.reader有很多选项来自定义格式docs.python.org/3.6/library/csv.html#csv-fmt-params
【解决方案3】:

更完整的解决方案:

import csv, gzip
class GZipCSVReader:
    def __init__(self, filename):
        self.gzfile = gzip.open(filename)
        self.reader = csv.DictReader(self.gzfile)
    def next(self):
        return self.reader.next()
    def close(self):
        self.gzfile.close()
    def __iter__(self):
        return self.reader.__iter__()

现在你可以像这样使用它了:

r = GZipCSVReader('my.csv')
for map in r:
    for k,v in map:
        print k,v
r.close()

编辑:按照下面的评论,一个更简单的方法怎么样:

def gzipped_csv(filename):
    with gzip.open(filename) as f:
        r = csv.DictReader(f)
        for row in r:
            yield row

然后让你

for row in gzipped_csv(filename):
    for k, v in row:
        print(k, v)

【讨论】:

  • 整洁。如果您可以添加 __enter_/__exit__() 上下文管理器方法,那么它可以与 with 语句一起使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
  • 2018-06-29
  • 2019-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多