我正在尝试用 Python 和 requests 库替换 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("*", "*"))
当我通过打开 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("*", "*"))
我一直在研究使用多部分选项(文件),但服务器似乎不喜欢这样。
所以我想知道是否有一种方法可以在 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
似乎服务器总是退回第一次身份验证尝试(?),但随后接受第二次。
将文件对象 (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
因此,第一次尝试像以前一样被阻止,但没有进行第二次尝试。
根据 Martijn Pieters(下)的说法,第二个问题可以用有故障的服务器(空行)来解释。我会调查这个,但如果有人有解决方法(除了使用 curl)我不介意听到它。
我仍然对请求库对于小字符串和文件对象的行为如此不同感到惊讶。文件对象在到达服务器之前不是序列化了吗?