如何解决将Pandas DataFrame作为Pickle写入S3
这是我的要求。
- 将熊猫数据框作为泡菜文件上传到AWS S3
- 由于环境原因,必须使用boto3,并且不能选择s3fs之类的选择
- 数据必须存在于内存中,并且无法写入临时文件
我创建了以下简单函数,将Pandas数据帧作为csv上传到s3:
def df_to_s3_csv(df,filename,sep=','):
s3 = boto3.resource('s3')
buffer = io.StringIO()
df.to_csv(buffer,sep=sep,index=False)
s3.Object(s3bucket,f'{s3_upload_path}/{filename}').put(Body=buffer.getvalue())
此功能可以正常工作,并且可以完成预期的工作。对于泡菜文件,我以类似的方式创建了以下函数:
def df_to_s3_pckl(df,filename):
s3 = boto3.resource('s3')
buffer = io.BytesIO()
df.to_pickle(buffer)
buffer.seek(0)
obj = s3.Object(s3bucket,f'{s3_upload_path}/{filename}')
obj.put(Body=buffer.getvalue())
我尝试使用带有和不带有seek
部分的函数,并且无论哪种方式都会引发以下错误:ValueError: I/O operation on closed file.
进一步研究该问题,发现buffer
一被调用就被认为closed
。可以通过发出以下命令来重现这一点:
df.to_pickle
以上打印buffer = io.BytesIO()
df.to_pickle(buffer)
print(buffer.closed)
。看来True
缓冲区已被BytesIO
关闭,因此无法引用其数据。如何解决此问题,或者有其他替代方案可以满足我的要求?我在SO上发现了几个有关如何使用boto3上载到S3的问题,但是没有关于如何使用BytesIO缓冲区上载由熊猫创建的泡菜文件的问题。
以下是该基本问题的可重现示例:
to_pickle
解决方法
看来该问题可以追溯到the pandas source code。最终,这可能是由于BytesIO
方法中意外使用to_pickle
对象而导致的熊猫中的错误。我使用以下代码设法在最小的可重现示例中解决了这个问题,该代码使用了dump
模块中的pickle
方法:
import pandas as pd
import numpy as np
import io
from pickle import dump
df = pd.DataFrame(np.random.randint(0,100,size=(4,4)))
buffer = io.BytesIO()
dump(df,buffer)
buffer.seek(0)
print(buffer.closed)
现在,打印语句将打印False
,并且可以访问BytesIO
流数据。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。