使用Python urllib2,如何在GET和POST之间进行流式传输?

时间:2014-07-23 00:30:28

标签: python streaming urllib2

我想编写代码将文件从一个站点传输到另一个站点。这可能是一个大文件,我想在不创建本地临时文件的情况下这样做。

我看到了使用mmap在Python上传大文件的技巧:" HTTP发布带有流媒体的大文件"但我真正需要的是一种将GET响应链接到创建POST。

之前有人这样做过吗?

2 个答案:

答案 0 :(得分:3)

你不能,或者至少不应该。

urllib2请求对象无法在运行时段将数据流式传输到它们中。而在另一个方向上,响应对象是类文件对象,理论上你可以read(8192)而不是read(),但对于大多数协议 - 包括HTTP - 它会经常或总是读取整个响应进入内存并从缓冲区中提供read(8192)个调用,使其毫无意义。所以,你必须拦截请求,从中窃取套接字,并手动处理它,此时urllib2正在阻碍你的工作,而不是它的帮助。

urllib2使一些事情变得容易,有些事情比它们应该更难,有些事情几乎是不可能的;如果它不容易,请停止使用它。


一种解决方案是使用更高级别的第三方库。例如,requests让你在中途(它可以很容易地从响应中流式传输,但只能在有限的情况下流式传输到响应中),而requests-toolbelt可以让你获得剩余的响应。那里的方式(它添加了各种流上传方式)。


另一种解决方案是使用较低级别的库。在这里,你甚至不必离开stdlib。 httplib强迫你一点一点地发送和接收事物,但这正是你想要的。在get请求中,您只需调用connectrequest,然后在响应对象上重复调用read(8192)。在帖子请求中,您拨打connectputrequestputheaderendheaders,然后重复send来自get请求的每个缓冲区,然后{{1}当你完成时。

事实上,在Python 3.2 +的getresponse(相当于2.x的http.client)中,httplib不一定是字符串,它可以是任何可迭代的或具有HTTPClient.requestread方法的任何类似文件的对象 ...其中包含一个响应对象。所以,就这么简单:

fileno

...当然,除了您可能想要制作合适的标题(您实际上可以使用import http.client getconn = httplib.HTTPConnection('www.example.com') getconn.request('GET', 'http://www.example.com/spam') getresp = getconn.getresponse() getconn = httplib.HTTPConnection('www.example.com') getconn.request('POST', 'http://www.example.com/eggs', body=getresp) getresp = getconn.getresponse() urllib.request的3.x版本来构建urllib2对象和不发送它...),并使用Request将主机和端口从URL中拉出而不是硬编码,并且您想要耗尽或至少检查来自POST请求的响应,依此类推。但这显示了困难的部分,而且并不难。

不幸的是,我认为这不适用于2.x。


最后,如果您熟悉urlparse,则至少有三个包装器(包括源代码分发附带的包装器)。我不确定是要将libcurl调用为高级别还是低于libcurl的级别,这有点像它自己奇怪的复杂轴。 :)

答案 1 :(得分:0)

对于此任务,

urllib2可能过于简单。您可能想要查看pycurl。我知道它支持流媒体。