Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python请求库上载大型XML文件_Python_Xml_Python Requests - Fatal编程技术网

使用Python请求库上载大型XML文件

使用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

我试图用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("*", "*"))
我一直在考虑使用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)