因此,我尝试将一个 parquet 文件读入内存,选择文件的块并将其上传到AWS S3 Bucket。我想编写健全性测试,以检查文件是否通过大小检查或MD5
哈希检查在本地和云文件之间正确上传。
我注意到的一件事是,将一个文件读入内存,无论是bytes
还是pd.DataFrame
/Table
,然后将同一个对象重新写入一个新文件,都会改变文件的大小,在我的例子中,与原始文件相比会增加文件的大小。
import pandas as pd
df = pd.read_parquet("data/example.parquet")
然后我简单地写:
from io import ByteIO
buffer = ByteIO()
df.to_parquet(buffer) # this can be done straight without BytesIO. I use it for clarity.
with open('copy.parquet', 'rb') as f:
f.write(buffer.getvalue())
现在对这两个文件使用ls -l
会给予不同的大小:
37089 Oct 28 16:57 data/example.parquet
37108 Dec 7 14:17 copy.parquet
有趣的是,我尝试使用一个工具,例如xxd
与diff
配对使用,令我惊讶的是,二进制差异分散在整个文件中,所以我认为这并不局限于元数据的差异。使用panda将两个文件重新加载到内存中会得到相同的表。值得一提的是,parquet文件同时包含Nan
和Nat
值。不幸的是,我不能共享该文件,但我可以用一个小样本来复制该行为。我也尝试使用Pyarrow
'的文件阅读功能,导致相同的文件大小:
import pyarrow as pa
import pyarrow.parquet as pq
with open('data/example.parquet', 'rb') as f:
buffer = pa.BufferReader(obj)
table = pq.read_table(buffer)
pq.write_table(table, 'copy.parquet')
我也试过在两个版本中打开compression='snappy'
,但它没有改变输出。
写回磁盘时是否遗漏了某些配置?
1条答案
按热度按时间6gpjuf901#
Pandas使用pyarrow来读/写parquet,所以结果是一样的,这并不奇怪。我不确定使用缓冲区与直接保存文件相比有什么清晰度,所以我在下面的代码中省略了它。
如果不是panda,而是直接使用pyarrow,则会显示出主要的 meta数据差异,因为panda除了正常的箭头元数据外,还添加了自己的模式。
虽然你说这不是这里的情况,所以可能的原因是,这个文件是由另一个系统写的不同版本的pyarrow,如Michael Delgado提到的意见snappy压缩是默认打开。Snappy is not deterministic between systems:
不跨库版本(甚至可能不跨体系结构)
这就解释了为什么你会在文件中看到不同。你可以尝试下面的代码,看看在同一台机器上,md5在文件之间是一样的,但是Pandas版本由于添加了 meta数据而更大。
目前,arrow s3编写器不检查完整性,但S3 API有这样的功能。我已经打开了一个issue,使其可以通过arrow访问。