I ran into a similar issue and would like to update the answer provided by @AKX. A couple of key pieces of context.
- You will need to use a pandas version that includes the fix "support binary file handles in to_csv". The example below was tested on Pandas 1.3.2, Python 3.8, and boto3 1.17.106.
- The answer by @AKX and the following example use the high level
s3.resource() API. I will also include an example for using the s3.client() API but keep in mind, they provide different methods for performing similar tasks.
Here is an example using boto3.resource("s3")
from io import BytesIO
import boto3
import pandas
from pandas import util
df = util.testing.makeMixedDataFrame()
s3_resource = boto3.resource("s3")
campaign_buffer = BytesIO()
df.to_csv(campaign_buffer, sep=",", index=False, mode="wb", encoding="UTF-8")
df.seek(0) # Make sure the stream position is at the beginning!
s3_resource.Object("test-bucket", "test_df_from_resource.csv").put(Body=campaign_buffer.getvalue())
You should then receive a confirmation message that looks similar to the following:
>> {'ResponseMetadata': {'RequestId': 'request-id-value',
'HostId': '###########',
'HTTPStatusCode': 200,
'HTTPHeaders': {'x-amz-id-2': '############',
'x-amz-request-id': '00000',
'date': 'Tue, 31 Aug 2021 00:00:00 GMT',
'x-amz-server-side-encryption': 'value',
'etag': '"xxxx"',
'server': 'AmazonS3',
'content-length': '0'},
'RetryAttempts': 0},
'ETag': '"xxxx"',
'ServerSideEncryption': 'value'}
And here is an example using boto3.client("s3")
from io import BytesIO
import boto3
import pandas
from pandas import util
df = util.testing.makeMixedDataFrame()
s3_client = boto3.client("s3")
campaign_buffer = BytesIO()
df.to_csv(campaign_buffer, sep=",", index=False, mode="wb", encoding="UTF-8")
df.seek(0)
s3_client.upload_fileobj(campaign_buffer, Bucket="test-bucket", Key="test_df_from_client.csv")
Hope seeing both examples helps anyone looking for an easy way to upload a Pandas dataframe to S3.