2017-02-18 15 views
3

У меня есть код, который извлекает объект AWS S3. Как читать этот StreamingBody с помощью csv.DictReader на Python?Как читать csv, хранящийся в S3 с помощью csv.DictReader?

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(???) 
+0

'csv.DictReader (streaming_body)'? – Leon

+0

'csv.DictReader (streaming_body)' возвращает ошибку "TypeError: аргумент 1 должен быть итератором". Запуск read() и декодирования() на нем перед его передачей (что я бы предпочел не делать, так как это загрузит весь файл в памяти) возвращает каждый символ из файла отдельно. – Jon

ответ

4

код будет выглядеть примерно так:

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 

lines = response[u'Body'].read().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) 
+0

@Jon, это ответ на ваш вопрос? – gary

+0

Да. Любой способ сделать это, чтобы мне не пришлось читать() весь файл в памяти? – Jon

+0

Решение 'codecs.getreader()' работало для меня для этой точной проблемы –