使用Python Requests库上传大型XML文件

M_b*_*eeb 5 python xml python-requests

我正在尝试用Python和请求库替换curl.使用curl,我可以使用curl -T选项将单个XML文件上载到REST服务器.我无法对请求库执行相同的操作.

基本方案有效:

payload = '<person test="10"><first>Carl</first><last>Sagan</last></person>'
headers = {'content-type': 'application/xml'}
r = requests.put(url, data=payload, headers=headers, auth=HTTPDigestAuth("*", "*"))
Run Code Online (Sandbox Code Playgroud)

当我通过打开XML文件将有效负载更改为更大的字符串时,.put方法挂起(我使用编解码器库来获取正确的unicode字符串).例如,使用66KB文件:

xmlfile = codecs.open('trb-1996-219.xml', 'r', 'utf-8')
headers = {'content-type': 'application/xml'}
content = xmlfile.read()
r = requests.put(url, data=content, headers=headers, auth=HTTPDigestAuth("*", "*"))
Run Code Online (Sandbox Code Playgroud)

我一直在研究使用multipart选项(文件),但服务器似乎不喜欢这样.

所以我想知道是否有办法模拟Python请求库中的curl -T行为.

更新1:程序挂起textmate,但在命令行上抛出UnicodeEncodeError错误.似乎一定是问题所在.所以问题是:有没有办法将unicode字符串发送到带有请求库的服务器?

更新2:由于Martijn Pieters的评论,UnicodeEncodeError消失了,但是出现了一个新问题.使用文字(ASCII)XML字符串,日志记录显示以下行:

2012-11-11 15:55:05,154 INFO Starting new HTTP connection (1): my.ip.address
2012-11-11 15:55:05,294 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 401 211
2012-11-11 15:55:05,430 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 201 0
Run Code Online (Sandbox Code Playgroud)

似乎服务器总是反弹第一次认证尝试(?)但接着第二次认证尝试.

使用传递给数据的文件对象(open('trb-1996-219.xml','rb')),日志文件显示:

2012-11-11 15:50:54,309 INFO Starting new HTTP connection (1): my.ip.address
2012-11-11 15:50:55,105 DEBUG "PUT /v1/documents?uri=/example/test.xml HTTP/1.1" 401 211
2012-11-11 15:51:25,603 WARNING Retrying (0 attempts remain) after connection broken by 'BadStatusLine("''",)': /v1/documents?uri=/example/test.xml
Run Code Online (Sandbox Code Playgroud)

因此,第一次尝试被阻止,但没有第二次尝试.

根据Martijn Pieters(下文),第二个问题可以通过故障服务器(空行)来解释.我将研究这个,但如果有人有一个解决方法(除了使用卷曲)我不介意听到它.

我仍然感到惊讶的是,请求库对于小字符串和文件对象的行为方式如此不同.文件对象在到达服务器之前是否已序列化?

Mar*_*ers 9

要PUT大文件,请不要将它们读入内存.只需将文件作为data关键字传递:

xmlfile = open('trb-1996-219.xml', 'rb')
headers = {'content-type': 'application/xml'}
r = requests.put(url, data=xmlfile, headers=headers, auth=HTTPDigestAuth("*", "*"))
Run Code Online (Sandbox Code Playgroud)

此外,您打开文件为unicode(从UTF-8解码).当您将其发送到远程服务器时,您需要原始字节,而不是unicode值,您应该将文件作为二进制文件打开.