2012-11-11 17 views
5

के साथ एक बड़ी एक्सएमएल फ़ाइल अपलोड करें मैं पाइथन & अनुरोध पुस्तकालय के साथ कर्ल को प्रतिस्थापित करने की कोशिश कर रहा हूं। कर्ल के साथ, मैं curl -T विकल्प के साथ एक एकल सर्वर फ़ाइल को एक आरईएसटी सर्वर पर अपलोड कर सकता हूं। मैं अनुरोध पुस्तकालय के साथ ऐसा करने में असमर्थ रहा हूं।पायथन अनुरोध पुस्तकालय

एक बुनियादी परिदृश्य काम करता है:

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 विधि रुक ​​जाता है (मैं कोडेक पुस्तकालय का उपयोग एक उचित यूनिकोड स्ट्रिंग प्राप्त करने के लिए)। उदाहरण के लिए, एक 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("*", "*")) 

मैं बहुखण्डीय विकल्प (फ़ाइलें) का उपयोग कर में देख रहा है, लेकिन सर्वर ने पसंद करने के लिए है कि नहीं लगता है।

तो मैं सोच रहा था कि पाइथन अनुरोध पुस्तकालय में curl -T व्यवहार को अनुकरण करने का कोई तरीका है या नहीं।

अद्यतन 1: प्रोग्राम टेक्स्टमेट में लटकता है, लेकिन कमांडलाइन पर यूनिकोड एन्कोड त्रुटि त्रुटि फेंकता है। लगता है कि समस्या होना चाहिए। तो सवाल यह होगा: क्या अनुरोध पुस्तकालय के साथ सर्वर पर यूनिकोड स्ट्रिंग भेजने का कोई तरीका है?

अद्यतन 2: मार्टिजन पीटर्स की टिप्पणी के लिए धन्यवाद यूनिकोड एन्कोडररर चला गया, लेकिन एक नया मुद्दा सामने आया। एक शाब्दिक (ASCII) एक्सएमएल स्ट्रिंग के साथ, प्रवेश निम्नलिखित लाइनों पता चलता है:

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 

लगता सर्वर हमेशा पहले प्रमाणीकरण प्रयास बाउंस लेकिन फिर दूसरा एक को स्वीकार करता है (?)।

एक फ़ाइल वस्तु के साथ

(खुला ('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 

तो, पहले ही प्रयास के रूप में पहले अवरुद्ध है, लेकिन कोई दूसरा प्रयास नहीं किया गया है।

मार्टिजन पीटर (नीचे) के अनुसार, दूसरा मुद्दा एक दोषपूर्ण सर्वर (खाली रेखा) द्वारा समझाया जा सकता है। मैं इसे देख लूंगा, लेकिन अगर किसी के पास वर्कअराउंड है (कर्ल का उपयोग करने के अलावा) मुझे यह सुनना बुरा नहीं लगेगा।

और मुझे अभी भी हैरान है कि अनुरोध पुस्तकालय छोटी स्ट्रिंग और फ़ाइल ऑब्जेक्ट के लिए अलग-अलग व्यवहार करता है। क्या सर्वर ऑब्जेक्ट को सर्वर से पहले पहुंचने से पहले क्रमबद्ध नहीं किया गया है?

उत्तर

9

बड़ी फ़ाइलों को पुट करने के लिए, उन्हें स्मृति में न पढ़ें। इसके अलावा

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

, आप यूनिकोड के रूप में फ़ाइल खोलने थे (UTF-8 से इसे डीकोड): बस data कीवर्ड के रूप में फ़ाइल गुजरती हैं। चूंकि आप इसे रिमोट सर्वर पर भेज देंगे, आपको कच्चे बाइट्स की आवश्यकता है, यूनिकोड मान नहीं, और आपको फ़ाइल को बाइनरी के रूप में खोलना चाहिए।

+0

त्वरित प्रतिक्रिया के लिए धन्यवाद। ऐसा करने से यूनिकोड एन्कोडररर हल हो गया लेकिन एक कनेक्शन एरर पेश किया गया: मैक्सरीट्रीरर। और सर्वर नीचे नहीं है, क्योंकि मैं कर्ल के साथ फ़ाइल अपलोड कर सकता हूं। –

+0

@M_breeb: आपको यह जानने के लिए 'लॉगिंग' मॉड्यूल का उपयोग करने की आवश्यकता है कि क्यों है; सर्वर को कनेक्शन प्रयास कुछ कारणों से विफल हो रहा है, * डेटा को पुट करने में सक्षम होने से पहले। 'Urllib3' कनेक्शन पूल कनेक्शन को पुनः प्रयास करता है, और यह प्रत्येक बार' लॉगिंग' मॉड्यूल से कनेक्ट करने में विफलता लॉग करेगा। –

+0

'आयात लॉगिंग', फिर' logging.basicConfig() 'उस आउटपुट को जल्दी से प्राप्त करने का सबसे बुनियादी तरीका है। –

1

डाइजेस्ट प्रमाणीकरण हमेशा आपको सर्वर पर कम से कम दो अनुरोध करने की आवश्यकता होती है। पहले अनुरोध में कोई प्रमाणीकरण डेटा नहीं है। यह पहला अनुरोध 401 "प्रमाणीकरण आवश्यक" प्रतिक्रिया कोड और एक पाचन चुनौती (जिसे नाउंस कहा जाता है) के साथ आपके पासवर्ड को इशारा करने के लिए उपयोग किया जा सकता है। (सटीक विवरण यहां कोई फर्क नहीं पड़ता)। इसका उपयोग सर्वर को दूसरा अनुरोध करने के लिए किया जाता है जिसमें आपके क्रेडेंशियल्स को चुनौती के साथ धोया जाता है।

समस्या यह दो चरण प्रमाणीकरण में है: आपकी बड़ी फ़ाइल पहले ही अनधिकृत अनुरोध (व्यर्थ में भेजें) के साथ पहले ही भेज दी गई थी लेकिन दूसरे अनुरोध पर फ़ाइल ऑब्जेक्ट पहले से ही ईओएफ स्थिति पर है। चूंकि फ़ाइल का आकार दूसरे अनुरोध के सामग्री-लंबाई शीर्षलेख में भी भेजा गया था, इसलिए यह सर्वर को उस फ़ाइल की प्रतीक्षा करने का कारण बनता है जो कभी नहीं भेजेगा।

आप अनुरोध सत्र का उपयोग करके इसे हल कर सकते हैं और पहले प्रमाणीकरण उद्देश्यों के लिए एक सरल अनुरोध कर सकते हैं (एक जीईटी अनुरोध कहें)। फिर एक ही पाचन अनुरोध जिसमें एक ही पाचन चुनौती का उपयोग करके वास्तविक पेलोड शामिल है, पहला अनुरोध बनाएं।

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) 
संबंधित मुद्दे