如何将POST数据流式传输到Python请求中?

vog*_*vog 5 python xml http generator python-requests

我正在使用Python requests库发送POST请求.生成POST数据的程序部分可以写入任意类文件对象(输出流).

我怎样才能使这两个部分合适?

我原本预计会requests为这个用例提供一个流媒体接口,但似乎没有.它只接受data从中读取的类文件对象作为参数.它不提供我可以编写的类文件对象.

这是Python HTTP库的基本问题吗?

目前为止的想法:

似乎最简单的解决方案是fork()让请求库与POST数据生成器通信管道.

有没有更好的办法?

或者,我可以尝试使POST数据生成器复杂化.但是,那个解析一个XML流(来自stdin)并生成一个新的XML流用作POST数据.然后我反过来也有同样的问题:XML序列化程序库想要写入类似文件的对象,我不知道XML序列化程序提供类似文件的对象的任何可能性,其他人可以从中读取.

我也知道最干净,经典的解决方案是coroutines,它通过generator(yield)在Python中有所提供.POST数据可以通过(yield)而不是类似文件的对象流式传输,并使用拉式解析器.

但是,是否可以requests接受POST数据的迭代器?是否有一个XML序列化器可以很容易地与yield?结合使用?

或者,是否有任何包装器对象将写入类似文件的对象转换为生成器,和/或提供包装迭代器的类文件对象?

mat*_*ata 6

request确实将迭代器或生成器作为data参数,详细信息在块编码请求中描述.在这种情况下,传输编码需要被分块,因为事先不知道数据大小.

这是一个非常简单的例子,使用a queue.Queue并且可以用作类似文件的对象进行编写:

import requests
import queue
import threading

class WriteableQueue(queue.Queue):

    def write(self, data):
        # An empty string would be interpreted as EOF by the receiving server
        if data:
            self.put(data)

    def __iter__(self):
        return iter(self.get, None)

    def close(self):
        self.put(None)

# quesize can be limited in case producing is faster then streaming
q = WriteableQueue(100)

def post_request(iterable):
    r = requests.post("http://httpbin.org/post", data=iterable)
    print(r.text)

threading.Thread(target=post_request, args=(q,)).start()

# pass the queue to the serializer that writes to it ...    
q.write(b'1...')
q.write(b'2...')

# closing ends the request
q.close()
Run Code Online (Sandbox Code Playgroud)