如何逐行读取azure blob?

时间:2018-01-26 02:16:40

标签: python azure azure-storage-blobs

我正在使用容器来对抗相当大的blob。数据是日志数据,每行是几kb。我希望BlockBlobService.get_blob_to_stream像流一样运行,但它会下载整个内容。我怎样才能实际流式传输blob ala:

with some_method as blobStream:
for line in blobStream:
    <do something with line>

根据我的需要,我无法下载整个流或将其保存在内存中我一次只需要一行。

3 个答案:

答案 0 :(得分:3)

因此,不存在能够逐行读取blob的功能。您需要为此提出自己的解决方案。

但是,使用get_blob_to_stream方法时,您当然可以读取blob的部分内容。如果你看到这个方法的签名:

def get_blob_to_stream(
        self, container_name, blob_name, stream, snapshot=None,
        start_range=None, end_range=None, validate_content=False,
        progress_callback=None, max_connections=2, lease_id=None,
        if_modified_since=None, if_unmodified_since=None, if_match=None,
        if_none_match=None, timeout=None):

您会注意到它有两个参数(start_rangeend_range)。这两个参数将使您能够读取部分blob内容,而不是读取整个blob。

你可以做的是读取一大块数据(一次说1MB),然后构建一些逻辑来逐行打破这些数据。

答案 1 :(得分:0)

我将blob设置为公开并执行以下操作,因为它是文本。不是超级理想,但它完成了工作。

import urllib.request

for line in urllib.request.urlopen(blob_url):
    <do something with line>

修改

我不得不面对的一个问题是套接字丢失,因为我正在使用一个实时blob。我不得不拍摄一张快照并使用一个会话,或者在处理完约5秒后我就会断开连接。

snapshotBlob = append_blob_service.snapshot_blob(container, blobName)

_params = {
    'snapshot': snapshotBlob.snapshot,
    'timeout': 20000,
}

s = requests.Session()

r = s.get(target_url, params=_params, stream=True, timeout=20000)

for line in in r.iter_lines():
    <do something with line>

答案 2 :(得分:0)

您可以在Get Blob Request Headers中使用Rangex-ms-range仅返回指定范围内blob的字节数。

您可以通过Python Storage SDK中的start_rangeend_range参数实现它。

例如,一个1GB blob文件被拆分为100个请求,每单位时间发送100个请求。然后将其下载到本地文件中以供后续处理。请确保使用正确的位置写入字节。但这需要系统有1GB的内存空间供其使用。

enter image description here

建议采用更优化的方法,在下载满足quota的每个容量时,可以同时将日志文件读入内存。

例如,blob被分为100个请求,每单位时间发送5个请求。按顺序运行20次。每5个请求被写入内存,并且将同时发送以下5个请求。通过这种方式,系统只分配大约quota的内存空间。

鉴于导致请求中断的网络不稳定需要在字节的请求范围内重写,我建议您将文件分成更多部分。

希望它对你有所帮助。