使用boto从S3中逐行读取文件?

gig*_*sko 18 python amazon-s3 boto

我在S3中有一个csv文件,我正在尝试读取标题行以获取大小(这些文件由我们的用户创建,因此它们几乎可以是任何大小).有没有办法用boto做到这一点?我想也许我可以使用python BufferedReader,但我无法弄清楚如何从S3键打开流.任何建议都会很棒.谢谢!

Mic*_*kov 25

您可能会发现https://pypi.python.org/pypi/smart_open对您的任务非常有用.

来自文档:

for line in smart_open.smart_open('s3://mybucket/mykey.txt'):
    print line
Run Code Online (Sandbox Code Playgroud)

  • 费用是多少?你最后下载整个文件只是为了阅读几行? (5认同)
  • 这太容易了!默认情况下支持gzip压缩文件! (3认同)
  • 使用外部库通常是不好的做法 - 您希望拥有最小的依赖关系,以便可以轻松升级和前进。 (3认同)

peo*_*eon 18

我知道这是一个非常古老的问题。

但至于现在,我们可以使用 s3_conn.get_object(Bucket=bucket, Key=key)['Body'].iter_lines()


小智 11

这是一个实际上逐行流式传输数据的解决方案:

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
Run Code Online (Sandbox Code Playgroud)

  • gzip要求不是最初的问题,但这正是我的用例所需要的.谢谢! (3认同)
  • 如果我们不使用 `GzipFile` 来解压缩它,它就不起作用,因为 `StreamingBody` 没有 `TextIOWrapper` 所需的 `readable` 属性 (3认同)

Joh*_*ein 10

看来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 '
Run Code Online (Sandbox Code Playgroud)

调用read(n)返回对象的下n个字节.

当然,这不会自动返回"标题行",但您可以使用足够大的数字来调用它以至少返回标题行.


alu*_*ach 10

stdlib 中的codecs模块提供了一种将字节流编码为文本流的简单方法,并提供了一个生成器来逐行检索此文本。它可以轻松地与 S3 一起使用:

import codecs

import boto3


s3 = boto3.resource("s3")
s3_object = s3.Object('my-bucket', 'a/b/c.txt')
line_stream = codecs.getreader("utf-8")

for line in line_stream(s3_object.get()['Body']):
    print(line)
Run Code Online (Sandbox Code Playgroud)


rob*_*tzp 8

使用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...
Run Code Online (Sandbox Code Playgroud)

  • 它不起作用。每次读第一行 (5认同)
  • 正如以下划线开头的_raw_stream属性所暗示的那样,这不是您应该访问流内容的方式。可以通过调用`obj.get()[“ body”]。read()`完整读取它们,也可以将其与`obj.get()[“ body”]。iter_lines()迭代为生成器。 (2认同)

one*_*ing 6

如果您想读取具有特定存储桶前缀(即在“子文件夹”中)的多个文件(逐行),您可以执行以下操作:

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'))
Run Code Online (Sandbox Code Playgroud)

这里的行是字节,所以我正在解码它们;但如果它们已经是一个字符串,你可以跳过它。


han*_*ast 6

使用boto3:

s3 = boto3.resource('s3')
obj = s3.Object(BUCKET, key)
for line in obj.get()['Body']._raw_stream:
    # do something with line
Run Code Online (Sandbox Code Playgroud)