文件创建和压缩功能相同

File creation and compress on the same function

我让 reader 不时从数据库读取数据并生成 csv 文件。我想在从数据库读取时创建压缩文件。

目前我正在创建 csv 文件,然后创建压缩文件。

def create_csv_file(data):
     filename = time.strftime("%Y%m%d-%H%M%S") + ".csv"
     filename_zip = time.strftime("%Y%m%d-%H%M%S") + ".zip"
     try:
           with open(filename, "w") as f:
               writer = csv.writer(f)
               for row in data:
                   writer.writerow(row)
               f.flush()

           with zipfile.ZipFile(filename_zip, 'w', zipfile.ZIP_DEFLATED) as myzip:
               myzip.write(filename, basename(filename))

     except Exception, e:
           print 'Error', e.message

我想直接创建没有 .csv 文件的 zip 文件并释放文件打开句柄。

我该怎么做?

在写入模式下使用ZipFile.writestr(使用StringIO收集csv.writer输出)或(在Python 3.6中)ZipFile.open

由于无法使用 zipfile 模块增量写入 csv 文件,因此您需要将所有 CVS 格式的数据存储在某处。如果数据量不是很大,内存是一个显而易见的选择。 @Davis Herring 基本上有正确的想法,除了在 Python 2 你需要使用 BytesIO and in Python 3, StringIO 作为中间缓冲区,然后将缓冲区中存储的格式化结果添加到最终的 ZipFile 你想要创建。

这是全部,尽显荣耀。请注意,我在其中留下了一些调试代码,您应该可以轻松删除这些代码,因为我已将您的原始代码作为注释保留在其中。顺便说一句,这两个时间戳可能不同,因为您调用了 time.strftime("%Y%m%d-%H%M%S") 两次。

import csv
import io
from pprint import pprint
from random import randint, seed
import time
import zipfile
import sys
InMemoryIO = getattr(io, 'BytesIO' if sys.version_info < (3,) else 'StringIO')

def create_csv_file(data):
    #filename = time.strftime("%Y%m%d-%H%M%S") + ".csv"
    #filename_zip = time.strftime("%Y%m%d-%H%M%S") + ".zip"
    # Use the same filenames everytime for testing.
    filename = "compress_me.csv"
    filename_zip = filename + ".zip"
    with InMemoryIO() as buffer:
        csv.writer(buffer).writerows(data)  # Convert data to csv format.
        with zipfile.ZipFile(filename_zip, 'w', zipfile.ZIP_DEFLATED) as myzip:
            myzip.writestr(filename, buffer.getvalue())


# Generate some random values to put in the csv file.
seed(42)  # Causes random numbers always be the same for testing.
data = [[randint(0, 100) for _ in range(10)] for _ in range(10)]
pprint(data)
create_csv_file(data)