使用Python请求库上载大型XML文件
我试图用Python替换curl&请求库。使用curl,我可以使用curl-T选项将单个XML文件上载到REST服务器。我无法对请求库执行同样的操作 一个基本的场景是:使用Python请求库上载大型XML文件,python,xml,python-requests,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 = re
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("*", "*"))
我一直在考虑使用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
似乎服务器始终会反弹第一次身份验证尝试(?),但随后会接受第二次身份验证尝试
通过将文件对象(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),我不介意听
我仍然感到惊讶的是,对于小字符串和文件对象,请求库的行为如此不同。文件对象在到达服务器之前不是已经序列化了吗?要放入大文件,不要将它们读入内存。只需将文件作为
数据
关键字传递:
xmlfile = open('trb-1996-219.xml', 'rb')
headers = {'content-type': 'application/xml'}
r = requests.put(url, data=xmlfile, headers=headers, auth=HTTPDigestAuth("*", "*"))
此外,您正在以unicode(从UTF-8解码)打开文件。当您将文件发送到远程服务器时,需要的是原始字节,而不是unicode值,您应该将文件作为二进制文件打开。摘要身份验证始终要求您至少向服务器发出两个请求。第一个请求不包含任何身份验证数据。第一个请求将失败,401“Authorization required”响应代码和摘要质询(称为nounce)将用于散列您的密码等(这里的确切细节无关紧要)。这用于向服务器发出第二个请求,其中包含使用质询散列的凭据 问题在于这两步身份验证中:第一个未经授权的请求已经发送了您的大文件(发送无效),但在第二个请求中,文件对象已经处于EOF位置。由于文件大小也是在第二个请求的Content-length头中发送的,这会导致服务器等待一个永远不会发送的文件 您可以使用requests会话来解决这个问题,并首先发出一个简单的身份验证请求(比如GET请求)。然后使用与第一个请求相同的摘要质询发出第二个PUT请求,该请求包含实际有效负载
sess = requests.Session()
sess.auth = HTTPDigestAuth("*", "*")
sess.get(url)
headers = {'content-type': 'application/xml'}
with codecs.open('trb-1996-219.xml', 'r', 'utf-8') as xmlfile:
sess.put(url, data=xmlfile, headers=headers)
我使用python中的请求来使用命令上载XML文件。 首先使用open()打开文件
file=open(“PIR.xsd”)
fragment=file.read()
file.close()
将XML文件的数据复制到请求的有效负载中并发布
payload={'key':'PFAkrzjmuZR957','xmlFragment':fragment}
r=requests.post(URL,data=payload)
检查html验证代码的步骤
打印(r.text)
感谢您的快速回复。这样做解决了UnicodeCodeer错误,但引入了ConnectionError:MaxRetryError。服务器没有关闭,因为我可以用curl上传文件。@M_breeb:您需要使用日志记录模块来找出原因;在能够放置数据之前,由于某种原因,与服务器的连接尝试失败。urllib3
连接池重试连接,它将记录每次连接到日志记录
模块时的失败。导入日志记录
,然后日志记录。basicConfig()
是快速获取输出的最基本方法。我已经开始了日志记录以及成功放置之间的区别(短文字字符串)和一个不成功的(rb文件对象)是警告“2012-11-11 15:37:27347在连接被“BadStatusLine”(“”)中断后重试(仍有0次尝试)警告”':/v1/documents?uri=/example/test。xml@M_breeb:您的服务器响应时状态行为空,违反了HTTP RFC。我担心这是服务器端问题,而不是Python问题。可能需要一个内容长度头,但服务器仍有故障。
sess = requests.Session()
sess.auth = HTTPDigestAuth("*", "*")
sess.get(url)
headers = {'content-type': 'application/xml'}
with codecs.open('trb-1996-219.xml', 'r', 'utf-8') as xmlfile:
sess.put(url, data=xmlfile, headers=headers)