web-dev-qa-db-ja.com

botoを使用してS3から1行ずつファイルを読み取りますか?

S3にcsvファイルがあり、ヘッダー行を読み取ってサイズを取得しようとしています(これらのファイルはユーザーが作成しているため、ほぼすべてのサイズになります)。 botoを使用してこれを行う方法はありますか? python BufferedReaderができるかもしれないと思ったが、S3キーからストリームを開く方法がわからない。どんな提案でも素晴らしい。ありがとう!

16
gignosko

Botoには、これを実行できるread()関数があるようです。ここに私のために働くいくつかのコードがあります:

_>>> import boto
>>> from boto.s3.key import Key
>>> conn = boto.connect_s3('ap-southeast-2')
>>> bucket = conn.get_bucket('bucket-name')
>>> k = Key(bucket)
>>> k.key = 'filename.txt'
>>> k.open()
>>> k.read(10)
'This text '
_

read(n)の呼び出しは、オブジェクトから次のnバイトを返します。

もちろん、これは「ヘッダー行」を自動的に返しませんが、少なくともヘッダー行を返すのに十分な数で呼び出すことができます。

10
John Rotenstein

https://pypi.python.org/pypi/smart_open がタスクに役立つことがあります。

ドキュメントから:

for line in smart_open.smart_open('s3://mybucket/mykey.txt'):
    print line
24

実際にデータを行ごとにストリーミングするソリューションは次のとおりです。

from io import TextIOWrapper
from gzip import GzipFile
...

# get StreamingBody from botocore.response
response = s3.get_object(Bucket=bucket, Key=key)
# if gzipped
gzipped = GzipFile(None, 'rb', fileobj=response['Body'])
data = TextIOWrapper(gzipped)

for line in data:
    # process line
8
kooshywoosh

Boto3を使用すると、未加工のストリームにアクセスし、行ごとに読み取ることができます。生ストリームは何らかの理由でプライベートプロパティであることに注意してください

s3 = boto3.resource('s3', aws_access_key_id='xxx', aws_secret_access_key='xxx')
obj = s3.Object('bucket name', 'file key')

obj.get()['Body']._raw_stream.readline() # line 1
obj.get()['Body']._raw_stream.readline() # line 2
obj.get()['Body']._raw_stream.readline() # line 3...
7
robertzp

Boto3の使用:

s3 = boto3.resource('s3')
obj = s3.Object(BUCKET, key)
for line in obj.get()['Body']._raw_stream:
    # do something with line
5
hansaplast

特定のバケットプレフィックス(つまり、「サブフォルダー」)を持つ複数のファイルを(行ごとに)読みたい場合は、次のようにします。

s3 = boto3.resource('s3', aws_access_key_id='<key_id>', aws_secret_access_key='<access_key>')

    bucket = s3.Bucket('<bucket_name>')
    for obj in bucket.objects.filter(Prefix='<your prefix>'):
        for line in obj.get()['Body'].read().splitlines():
            print(line.decode('utf-8'))

ここで行はバイトなので、デコードしています。ただし、既に文字列である場合は、スキップできます。

0
oneschilling

ファイルを読み取るための最も動的で低コストの方法は、必要な行数が見つかるまで各バイトを読み取ることです。

line_count = 0
line_data_bytes = b''

while line_count < 2 :

    incoming = correlate_file_obj['Body'].read(1)
    if incoming == b'\n':
        line_count = line_count + 1

    line_data_bytes = line_data_bytes + incoming

logger.debug("read bytes:")
logger.debug(line_data_bytes)

line_data = line_data_bytes.split(b'\n')

ヘッダーサイズを変更できる場合、ヘッダーサイズを推測する必要はありません。ファイル全体をダウンロードする必要はなく、サードパーティのツールは必要ありません。ファイル内の行の区切りが正しいことを確認する必要があり、適切なバイト数を読み取ってそれを見つける必要があります。

0
KiteCoder