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

时间:2016-10-13 08:25:30

标签: python xml http python-requests generator

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

如何使这两个部分合适?

我原以为requests为这个用例提供了一个流接口,但它似乎并没有。它只接受data参数作为文件类对象,读取。它没有提供类似文件的对象,我可以

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

到目前为止的想法:

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

有更好的方法吗?

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

我也意识到最简洁,经典的解决方案是协同程序,它通过生成器(yield)在Python中有所提供。 POST数据可以通过(yield)而不是类似文件的对象流式传输,并使用拉式解析器。

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

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

2 个答案:

答案 0 :(得分:5)

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

这是一个使用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()

答案 1 :(得分:0)

将需要数据接收器的推送接口的数据生成器与需要其数据源的拉接口的数据使用者连接的唯一方法是通过中间缓冲区。这样的系统只能通过在" parallel"中运行生产者和消费者来操作。 - 生产者填充缓冲区,消费者从中读取,每个都在必要时被暂停。可以使用协同多任务来模拟这种并行性,其中当缓冲区已满时,生产者向消费者产生控制,并且当缓冲区变空时,消费者将控制返回给生产者。通过采用发电机方法,您将为您的案例构建定制的协作式多任务解决方案,与简单的基于管道的方法相比,这种方法几乎不会变得更简单,其中生产者和消费者的调度责任完全取决于OS。