使用Python“请求”库读取流式http响应

2024-05-19 11:30:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用由Kubernetes提供的事件流 使用requests模块的api。我遇到了一个看起来像 缓冲问题:requests模块似乎滞后于一个事件。

我有这样的代码:

r = requests.get('http://localhost:8080/api/v1beta1/watch/services',
                 stream=True)

for line in r.iter_lines():
    print 'LINE:', line

由于Kubernetes发出事件通知,此代码将只显示 当新事件出现时发出的最后一个事件,它使 对于需要响应服务的代码几乎完全无用 添加/删除事件。

我通过在子进程中生成curl而不是使用 requests库:

p = subprocess.Popen(['curl', '-sfN',
                      'http://localhost:8080/api/watch/services'],
                     stdout=subprocess.PIPE,
                     bufsize=1)

for line in iter(p.stdout.readline, b''):
    print 'LINE:', line

这是可行的,但牺牲了一些灵活性。有没有办法 避免使用requests库的缓冲问题?


Tags: 模块代码inapilocalhosthttpforservice
1条回答
网友
1楼 · 发布于 2024-05-19 11:30:00

此行为是由于iter_lines的错误实现造成的 方法。

iter_lines迭代chunk_size块中的响应内容 使用iter_content迭代器的数据。如果少于 chunk_size可从远程读取的数据字节 服务器(通常在读取 输出),读取操作将阻塞到 数据可用。

我已经编写了自己的iter_lines例程,它运行正常:

import os


def iter_lines(fd, chunk_size=1024):
    '''Iterates over the content of a file-like object line-by-line.'''

    pending = None

    while True:
        chunk = os.read(fd.fileno(), chunk_size)
        if not chunk:
            break

        if pending is not None:
            chunk = pending + chunk
            pending = None

        lines = chunk.splitlines()

        if lines and lines[-1]:
            pending = lines.pop()

        for line in lines:
            yield line

    if pending:
        yield(pending)

这是因为os.read将返回小于chunk_size字节 而不是等待缓冲区填满。

相关问题 更多 >

    热门问题