我让读者不时地从数据库中读取数据并生成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文件,并释放文件打开句柄。
我该怎么做?
答案 0 :(得分:1)
在写入模式下使用ZipFile.writestr
(使用StringIO
收集csv.writer
输出)或(在Python 3.6中)ZipFile.open
。
答案 1 :(得分:1)
由于无法使用zipfile
模块以递增方式编写csv文件,因此您需要将所有CVS格式的数据存储在某处。如果数据量不是很大,那么内存就是一个明显的选择。 @Davis Herring基本上有正确的想法,除了在Python 2中你需要使用BytesIO
和在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)