Python XlsxWriter:内存中为什么会给出损坏的字节序列?
我正在生成一个excel文件,并将其返回到flask应用程序中下载。如果我使用Python XlsxWriter:内存中为什么会给出损坏的字节序列?,python,xlsxwriter,bytesio,Python,Xlsxwriter,Bytesio,我正在生成一个excel文件,并将其返回到flask应用程序中下载。如果我使用“内存中”:True,则文件已损坏,excel无法打开它。如果直接写入磁盘,同样的代码也可以工作。对于内存中的代码,我遵循 我怀疑字节是否不同,所以我编写了一个小脚本进行测试,它们确实略有不同(5730个字节中有44个字节) 这是我的脚本生成的相同工作簿,一个在内存中,一个在磁盘上。然后比较字节,发现它们是不同的。为什么? from io import BytesIO from xlsxwriter import W
“内存中”:True
,则文件已损坏,excel无法打开它。如果直接写入磁盘,同样的代码也可以工作。对于内存中的代码,我遵循
我怀疑字节是否不同,所以我编写了一个小脚本进行测试,它们确实略有不同(5730个字节中有44个字节)
这是我的脚本生成的相同工作簿,一个在内存中,一个在磁盘上。然后比较字节,发现它们是不同的。为什么?
from io import BytesIO
from xlsxwriter import Workbook
def fill_workbook(workbook):
"""Populate the workbook with some test data"""
first_sheet = workbook.add_worksheet("First")
first_sheet.write(0, 0, "test")
next_sheet = workbook.add_worksheet("Next")
next_sheet.write(0, 0, "sample")
next_sheet.write(0, 1, "value")
workbook.close()
def get_bytes():
"""Get the bytes for the in-memory and on-disk workbooks"""
output = BytesIO()
in_mem = Workbook(output, {'in_memory': True})
filename = "direct.xlsx"
on_disk = Workbook(filename)
fill_workbook(in_mem)
fill_workbook(on_disk)
output.seek(0)
mem_bytes = output.read()
with open(filename, "rb") as f:
disk_bytes = f.read()
return mem_bytes, disk_bytes
def compare_bytes():
"""Compare the bytes of the two workbooks"""
mem_bytes, disk_bytes = get_bytes()
print(mem_bytes == disk_bytes)
same = 0
diff = 0
for mb, db in zip(mem_bytes, disk_bytes):
if mb == db:
same += 1
else:
diff +=1
print(f"{same} bytes same")
print(f"{diff} bytes different")
if __name__ == '__main__':
compare_bytes()
我用
XlsxWriter==1.2.8
在python3.7.3
上运行脚本,当内存中的设置为False
时,它对我有效。让我们看看in_memory参数在XlsxWriter源代码中的实际作用:
由于其中一个Excel元数据文件中的时间戳,任何两个相隔超过一秒(或可能是一毫秒)的XlsxWriter文件都将不同。为了确保文件是二进制的,您应该通过set\u properties()
workbook方法设置“创建”日期:
for file_id, file_data in enumerate(xml_files):
os_filename, xml_filename, is_binary = file_data
if self.in_memory:
# Set sub-file timestamp to Excel's timestamp of 1/1/1980.
zipinfo = ZipInfo(xml_filename, (1980, 1, 1, 0, 0, 0))
# Copy compression type from parent ZipFile.
zipinfo.compress_type = xlsx_file.compression
if is_binary:
xlsx_file.writestr(zipinfo, os_filename.getvalue())
else:
xlsx_file.writestr(zipinfo,
os_filename.getvalue().encode('utf-8'))`
else:
# The sub-files are tempfiles on disk, i.e, not in memory.
# Set sub-file timestamp to 31/1/1980 due to portability
# issues setting it to Excel's timestamp of 1/1/1980.
timestamp = time.mktime((1980, 1, 31, 0, 0, 0, 0, 0, -1))
os.utime(os_filename, (timestamp, timestamp))
try:
xlsx_file.write(os_filename, xml_filename)
os.remove(os_filename)