将数据帧直接保存到csv到s3 Python

use*_*275 87 python csv amazon-s3 dataframe boto3

我有一个pandas DataFrame,我想上传到新的CSV文件.问题是我不想在将文件传输到s3之前将其保存在本地.是否有像to_csv这样的方法直接将数据帧写入s3?我正在使用boto3.
这是我到目前为止:

import boto3
s3 = boto3.client('s3', aws_access_key_id='key', aws_secret_access_key='secret_key')
read_file = s3.get_object(Bucket, Key)
df = pd.read_csv(read_file['Body'])

# Make alterations to DataFrame

# Then export DataFrame to CSV through direct transfer to s3
Run Code Online (Sandbox Code Playgroud)

Ste*_*fan 109

您可以使用:

from io import StringIO # python3; python2: BytesIO 
import boto3

bucket = 'my_bucket_name' # already created on S3
csv_buffer = StringIO()
df.to_csv(csv_buffer)
s3_resource = boto3.resource('s3')
s3_resource.Object(bucket, 'df.csv').put(Body=csv_buffer.getvalue())
Run Code Online (Sandbox Code Playgroud)

  • 如果这是一个大文件,这对内存有什么作用? (5认同)
  • 我得到`TypeError:unicode参数,使用`StringIO`时出现'str'`错误.我使用了`BytesIO`,它工作得非常好._Note:这是在Python 2.7_ (4认同)
  • 如果文件更大,那么您可用的 RAM 操作将失败,并且会出现异常(不知道是哪一个)。这应该被接受为答案 (2认同)
  • 什么是“bucket”对象?你是怎么创造的? (2认同)
  • “bucket”是您在 S3 上存储对象的位置。该代码假设您已经创建了存储此内容的目标(例如:目录)。请参阅 [S3 文档](https://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html) (2认同)

mic*_*234 48

我喜欢s3fs,它允许你使用s3(几乎)像本地文件系统.

你可以这样做:

import s3fs

bytes_to_write = df.to_csv(None).encode()
fs = s3fs.S3FileSystem(key=key, secret=secret)
with fs.open('s3://bucket/path/to/file.csv', 'wb') as f:
    f.write(bytes_to_write)
Run Code Online (Sandbox Code Playgroud)

s3fs仅支持rbwb打开文件的模式,这就是我做这个的原因bytes_to_write.

  • @j' `s3fs` 似乎不支持追加模式。 (2认同)

Ami*_*aha 38

您可以直接使用S3路径。我正在使用Pandas 0.24.1

In [1]: import pandas as pd

In [2]: df = pd.DataFrame( [ [1, 1, 1], [2, 2, 2] ], columns=['a', 'b', 'c'])

In [3]: df
Out[3]:
   a  b  c
0  1  1  1
1  2  2  2

In [4]: df.to_csv('s3://experimental/playground/temp_csv/dummy.csv', index=False)

In [5]: pd.__version__
Out[5]: '0.24.1'

In [6]: new_df = pd.read_csv('s3://experimental/playground/temp_csv/dummy.csv')

In [7]: new_df
Out[7]:
   a  b  c
0  1  1  1
1  2  2  2

Run Code Online (Sandbox Code Playgroud)

发行公告:

S3文件处理

熊猫现在使用s3fs处理S3连接。这不应破坏任何代码。但是,由于s3fs不是必需的依赖项,因此您将需要单独安装它,例如以前版本的panda中的boto。GH11915

  • 这绝对是现在最简单的答案,它在后台使用了s3fs,因此您需要将其添加到您的requirements.txt中 (5认同)
  • 我喜欢它很简单,但似乎它并没有真正起作用,因为我不断收到以下错误“NoCredentialsError:无法找到凭据”。有什么建议么? (3认同)
  • 我正在使用pandas 0.24.2,得到的是“ NotImplementedError:不支持文本模式,使用mode ='wb'并管理字节”。有什么建议么? (3认同)
  • 我可以确认这不适用于 pandas <= 0.23.4,因此请务必升级到 pandas 0.24 (2认同)

ern*_*cyp 30

这是一个更新的答案:

import s3fs

s3 = s3fs.S3FileSystem(anon=False)

# Use 'w' for py3, 'wb' for py2
with s3.open('<bucket-name>/<filename>.csv','w') as f:
    df.to_csv(f)
Run Code Online (Sandbox Code Playgroud)

StringIO的问题在于它会吞噬你的记忆.使用此方法,您将文件流式传输到s3,而不是将其转换为字符串,然后将其写入s3.将pandas数据帧及其字符串副本保存在内存中似乎非常低效.

如果你在ec2瞬间工作,你可以赋予它一个IAM角色,使其能够写入s3,因此你不需要直接传递凭证.但是,您也可以通过将凭据传递给S3FileSystem()函数来连接到存储桶.请参阅文档:https://s3fs.readthedocs.io/en/latest/


gab*_*bra 12

您还可以使用AWS Data Wrangler

import awswrangler as wr
    
wr.s3.to_csv(
    df=df,
    path="s3://...",
)
Run Code Online (Sandbox Code Playgroud)

请注意,它将为您处理分段上传以加快上传速度。


mha*_*wke 11

如果传递None,to_csv()则数据的第一个参数将作为字符串返回.从那里可以轻松地将其一次性上传到S3.

也应该可以将StringIO对象传递给to_csv(),但使用字符串会更容易.


Har*_*_pb 8

我发现这可以使用 is 来完成,client而不仅仅是resource.

from io import StringIO
import boto3
s3 = boto3.client("s3",\
                  region_name=region_name,\
                  aws_access_key_id=aws_access_key_id,\
                  aws_secret_access_key=aws_secret_access_key)
csv_buf = StringIO()
df.to_csv(csv_buf, header=True, index=False)
csv_buf.seek(0)
s3.put_object(Bucket=bucket, Body=csv_buf.getvalue(), Key='path/test.csv')
Run Code Online (Sandbox Code Playgroud)


Azi*_*lto 5

我使用AWS Data Wrangler。例如:

import awswrangler as wr
import pandas as pd

# read a local dataframe
df = pd.read_parquet('my_local_file.gz')

# upload to S3 bucket
wr.s3.to_parquet(df=df, path='s3://mys3bucket/file_name.gz')
Run Code Online (Sandbox Code Playgroud)

这同样适用于 csv 文件。使用 和 并read_parquet带有正确的文件扩展名,而不是 和。to_parquetread_csvto_csv