首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Python "requests“库读取流http响应

使用Python "requests“库读取流http响应
EN

Stack Overflow用户
提问于 2015-01-26 00:57:48
回答 1查看 13.6K关注 0票数 13

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

我的代码看起来像这样:

代码语言:javascript
复制
r = requests.get('http://localhost:8080/api/v1beta1/watch/services',
                 stream=True)

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

当Kubernetes发出事件通知时,此代码将仅显示新事件传入时发出的最后一个事件,这使得它对于需要响应服务添加/删除事件的代码几乎毫无用处。

我已经通过在子进程中生成curl而不是使用requests库解决了这个问题:

代码语言:javascript
复制
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库出现这种缓冲问题?

EN

回答 1

Stack Overflow用户

发布于 2015-01-27 02:09:37

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

iter_lines使用iter_content迭代器遍历chunk_size数据块中的响应内容。如果可用于从远程服务器读取的数据少于chunk_size字节(在读取输出的最后一行时通常是这种情况),则读取操作将阻塞,直到有chunk_size字节的数据可用为止。

我已经编写了自己的iter_lines例程,可以正确运行:

代码语言:javascript
复制
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字节的数据,而不是等待缓冲区填充。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28138932

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档