【问题标题】:How do I read a csv stored in S3 with csv.DictReader?如何使用 csv.DictReader 读取存储在 S3 中的 csv?
【发布时间】:2019-05-22 04:44:29
【问题描述】:

我有获取 AWS S3 对象的代码。如何使用 Python 的 csv.DictReader 读取这个 StreamingBody?

import boto3, csv

session = boto3.session.Session(aws_access_key_id=<>, aws_secret_access_key=<>, region_name=<>)
s3_resource = session.resource('s3')
s3_object = s3_resource.Object(<bucket>, <key>)
streaming_body = s3_object.get()['Body']

#csv.DictReader(???)

【问题讨论】:

  • csv.DictReader(streaming_body)?
  • csv.DictReader(streaming_body) 返回错误“TypeError: argument 1 must be an iterator”。在传递它之前运行 read() 和 decode() (我不想这样做,因为这会将整个文件加载到内存中)分别从文件中返回每个字符。

标签: python csv amazon-web-services amazon-s3


【解决方案1】:

代码是这样的:

import boto3
import csv

# get a handle on s3
s3 = boto3.resource(u's3')

# get a handle on the bucket that holds your file
bucket = s3.Bucket(u'bucket-name')

# get a handle on the object you want (i.e. your file)
obj = bucket.Object(key=u'test.csv')

# get the object
response = obj.get()

# read the contents of the file and split it into a list of lines

# for python 2:
lines = response[u'Body'].read().split()

# for python 3 you need to decode the incoming bytes:
lines = response['Body'].read().decode('utf-8').split()

# now iterate over those lines
for row in csv.DictReader(lines):

    # here you get a sequence of dicts
    # do whatever you want with each line here
    print(row)

您可以在实际代码中稍微压缩一下,但我尝试逐步保持它以使用 boto3 显示对象层次结构。

根据您关于避免将整个文件读入内存的评论进行编辑:我没有遇到这个要求,所以不能权威地说,但我会尝试包装流,这样我就可以获得一个文本文件- 类似迭代器。例如,您可以使用 codecs 库将上面的 csv 解析部分替换为:

for row in csv.DictReader(codecs.getreader('utf-8')(response[u'Body'])):
    print(row)

【讨论】:

  • @Jon,这回答了你的问题吗?
  • 是的。有什么方法可以让我不必将整个文件读入内存?
  • codecs.getreader() 解决方案为我解决了这个确切的问题
  • 上面的代码对我不起作用,但稍作修改:response['Body'].read().decode('utf-8').split()。我正在使用 Python 3.7
  • 有没有办法在读取后保持文件完整性而不清理?
猜你喜欢
  • 1970-01-01
  • 2021-10-25
  • 2014-09-02
  • 2015-08-29
  • 2016-09-28
  • 2019-11-12
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多