使用 boto 从 S3 流式传输 .gz 文件时无限循环
Infinite loop when streaming a .gz file from S3 using boto
我正在尝试使用 boto 从 S3 流式传输 .gz 文件并遍历解压缩文本文件的行。神秘的是,循环永远不会终止;读取整个文件后,迭代从文件开头重新开始。
假设我创建并上传了如下输入文件:
> echo '{"key": "value"}' > foo.json
> gzip -9 foo.json
> aws s3 cp foo.json.gz s3://my-bucket/my-location/
我 运行 以下 Python 脚本:
import boto
import gzip
connection = boto.connect_s3()
bucket = connection.get_bucket('my-bucket')
key = bucket.get_key('my-location/foo.json.gz')
gz_file = gzip.GzipFile(fileobj=key, mode='rb')
for line in gz_file:
print(line)
结果是:
b'{"key": "value"}\n'
b'{"key": "value"}\n'
b'{"key": "value"}\n'
...forever...
为什么会这样?我认为一定有一些非常基本的东西是我遗漏的。
啊,博托。问题是如果你在密钥被完全读取一次后调用它,read 方法会重新下载密钥(比较 read 和 next 方法以查看差异)。
这不是最干净的方法,但它解决了问题:
import boto
import gzip
class ReadOnce(object):
def __init__(self, k):
self.key = k
self.has_read_once = False
def read(self, size=0):
if self.has_read_once:
return b''
data = self.key.read(size)
if not data:
self.has_read_once = True
return data
connection = boto.connect_s3()
bucket = connection.get_bucket('my-bucket')
key = ReadOnce(bucket.get_key('my-location/foo.json.gz'))
gz_file = gzip.GzipFile(fileobj=key, mode='rb')
for line in gz_file:
print(line)
谢谢zweiterlinde for the wonderful insight and 。
我一直在寻找将压缩的 S3 对象直接读入 Pandas DataFrame 的解决方案,并使用他的包装器,可以用两行表示:
with gzip.GzipFile(fileobj=ReadOnce(bucket.get_key('my/obj.tsv.gz')), mode='rb') as f:
df = pd.read_csv(f, sep='\t')
我正在尝试使用 boto 从 S3 流式传输 .gz 文件并遍历解压缩文本文件的行。神秘的是,循环永远不会终止;读取整个文件后,迭代从文件开头重新开始。
假设我创建并上传了如下输入文件:
> echo '{"key": "value"}' > foo.json
> gzip -9 foo.json
> aws s3 cp foo.json.gz s3://my-bucket/my-location/
我 运行 以下 Python 脚本:
import boto
import gzip
connection = boto.connect_s3()
bucket = connection.get_bucket('my-bucket')
key = bucket.get_key('my-location/foo.json.gz')
gz_file = gzip.GzipFile(fileobj=key, mode='rb')
for line in gz_file:
print(line)
结果是:
b'{"key": "value"}\n'
b'{"key": "value"}\n'
b'{"key": "value"}\n'
...forever...
为什么会这样?我认为一定有一些非常基本的东西是我遗漏的。
啊,博托。问题是如果你在密钥被完全读取一次后调用它,read 方法会重新下载密钥(比较 read 和 next 方法以查看差异)。
这不是最干净的方法,但它解决了问题:
import boto
import gzip
class ReadOnce(object):
def __init__(self, k):
self.key = k
self.has_read_once = False
def read(self, size=0):
if self.has_read_once:
return b''
data = self.key.read(size)
if not data:
self.has_read_once = True
return data
connection = boto.connect_s3()
bucket = connection.get_bucket('my-bucket')
key = ReadOnce(bucket.get_key('my-location/foo.json.gz'))
gz_file = gzip.GzipFile(fileobj=key, mode='rb')
for line in gz_file:
print(line)
谢谢zweiterlinde for the wonderful insight and
我一直在寻找将压缩的 S3 对象直接读入 Pandas DataFrame 的解决方案,并使用他的包装器,可以用两行表示:
with gzip.GzipFile(fileobj=ReadOnce(bucket.get_key('my/obj.tsv.gz')), mode='rb') as f:
df = pd.read_csv(f, sep='\t')