LoginSignup
7
2

More than 5 years have passed since last update.

PythonでCSVファイルをS3 SELECTする

Posted at

概要

サンプルデータを準備

  • なんでもいいんですが、ちょっとした大きさのテストファイルを作成します
make_testfile.py
import hashlib

with open('testfile.csv', 'w') as f:
    for i in range(10000):
        f.write('{},{}\n'.format(i, hashlib.sha512(str(i).encode()).hexdigest()))
  • 連番+適当なハッシュ文字列の2カラム、1万行のファイルができます
  • ファイルサイズは1.3MB程度です
testfile.csv
0,31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99
1,4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a
2,40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114
(省略)
  • S3バケットへアップロードします
  • マネジメントコンソールからでもOKです
$ aws s3 cp testfile.csv s3://my-s3select/
upload: ./testfile.csv to s3://my-s3select/testfile.csv

SELECTするコード

  • 返される結果は65000バイトに分割されるようです
  • 結果の意味にかかわらずブツ切りにされるので、一旦全体を受け取って結合して使用する必要がありそうです
  • ここではローカルファイルとして出力します
    • 実際はtempfileを使う感じかなと思います
    • 巨大にならない場面ならメモリ上で処理するかも
s3select.py
import boto3

s3 = boto3.client('s3')
response = s3.select_object_content(
    Bucket='my-s3select',
    Key='testfile.csv',
    ExpressionType='SQL',
    RequestProgress={'Enabled': True},
    Expression="SELECT * FROM S3Object",
    InputSerialization={'CSV': {}},
    OutputSerialization={'CSV': {}},
)

end_event_received = False
with open('output.csv', 'wb') as f:
    for event in response['Payload']:
        if 'Records' in event:
            f.write(event['Records']['Payload'])
        elif 'End' in event:
            end_event_received = True
if not end_event_received:
    raise Exception('処理が不完全です')

# あとはoutput.csvを開き直して処理する
7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2