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



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

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

我本来期望requests为这个用例提供一个流接口,但它似乎没有。它只接受从中读取的类文件对象作为data参数。它没有提供一个类似文件的对象,我可以在其中写入

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

目前为止的想法:

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

有更好的方法吗?

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

我也意识到,最干净、最经典的解决方案是协程,它在Python中可以通过生成器(yield)获得。POST数据可以通过(yield)而不是类似文件的对象进行流传输,并使用拉解析器。

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

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

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

下面是一个非常简单的例子,它使用了一个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()

连接需要为其数据接收提供推送接口的数据生产者和需要为其数据源提供拉取接口的数据消费者的唯一方法是通过中间缓冲区。这样的系统只能通过"并行"运行生产者和消费者来运行——生产者填充缓冲区,消费者从缓冲区中读取,每个生产者都在必要时被挂起。这种并行性可以通过协作多任务来模拟,当缓冲区满时,生产者将控制权交给消费者,当缓冲区空时,消费者将控制权交还给生产者。通过采用生成器方法,您将为您的情况构建一个定制的协作多任务解决方案,与简单的基于管道的方法相比,这几乎不会更简单,在管道方法中,调度生产者和消费者的责任完全由操作系统承担。

最新更新