2017-07-01 20 views
5

मैं वर्तमान में पाइथन 2.7 अनुरोध लाइब्रेरी का उपयोग कर रहा हूं और ऑर्डर किए गए हेडर के लिए कोई समर्थन नहीं है। मैं पोस्ट के लिए आदेशित डेटा डाल सकता हूं और प्राप्त कर सकता हूं (एक आदेशित शब्दकोश की तरह) लेकिन हेडर के लिए कोई समर्थन नहीं है। यहां तक ​​कि पाइथन 3पायथन - ऑर्डर किए गए हेडर HTTP अनुरोध

मुझे HTTP प्रोटोकॉल आरएफसी पता है, यह इंगित करता है कि हेडर का क्रम महत्वहीन है, लेकिन समस्या यह है कि जिस तीसरे पक्ष की सेवा मैं कार्यान्वित कर रहा हूं वह काम नहीं करता है जब तक कि हेडर क्रम में न हों। मुझे यह पता है क्योंकि मैंने अन्य भाषाओं में ऑर्डर करने वाले हेडर अनुरोधों को लागू किया है और यह काम करता है (जावा की तरह) और हां, मैं इसमें से 100% निश्चित हूं, क्योंकि मैंने यह सुनिश्चित करने के लिए निरीक्षण किया कि यह अनुरोधों के बीच एकमात्र अंतर है । लेकिन मेरे पास पाइथन में पहले से ही 5,000+ रेखाएं हैं इसलिए माइग्रेट करना इस तरह की समस्या के कारण इतनी दर्दनाक निर्णय है।

एकमात्र समाधान मैंने सोचा है कि टीसीपी के शीर्ष पर http प्रोटोकॉल को लागू करना है, लेकिन यह एक स्मार्ट समाधान नहीं है। मेरे पास उपलब्ध समाधान के रूप में कोड की समान गुणवत्ता नहीं हो सकती है और यह मेरे कोड के लिए विफलता का एक संभावित बिंदु है।

एक सरल कोड उदाहरण देखें मैं नीचे है:

data=(("param1","something"), 
("param2","something_else")) 

headers={'id': 'some_random_number', 
'version':'some_random_number' , 
'signature':'some_random_number' , 
        'Content-Type':'application/x-www-form-urlencoded' , 
        'charset':'utf-8' , 
        'Content-Length':str(len(urllib.urlencode(data))) , 
        'name':'random' , 
        'User-Agent':'Firefox' , 
        'Connection':'Keep-Alive' , 
        'Accept-Encoding':'gzip'} 

requests.post("myservice.com",headers=headers, data=data) 

अनुरोध हेडर के आदेश (, सिर्फ एक उदाहरण भर में अपनी बात पाने के लिए वास्तविक नहीं क्रम)

'version':'some_random_number' 
'Accept-Encoding':'gzip' 
'id': 'some_random_number' 
'User-Agent':'Firefox' 
'signature':'some_random_number' 
'Connection':'Keep-Alive' 
'Content-Type':'application/x-www-form-urlencoded' 
'charset':'utf-8' 
'name':'random' 
ऐसे ही भेज रहा है

जो मेरे लिए एक समस्या है। मुझे नहीं पता कि इस बिंदु पर क्या करना है। किसी भी मदद की बहुत सराहना की। मैं पुस्तकालय urllib की कोशिश की कोई समर्थन

+0

आदेश दिया गया था आदेश काम? –

+1

नहीं, ऑर्डर लाइब्रेरी का उपयोग करते हुए .items() अपवाद, अनुरोध पुस्तकालय के लिए देता है, क्योंकि अनुरोध लाइब्रेरी आइटम() विधि का उपयोग करके हेडर को पार करती है और आदेशित आदेश के लिए ऐसा कोई समर्थन नहीं है। यह कुछ पुराने अनुरोध संस्करण में काम करता था जो मैंने दूसरे स्टैक ओवरफ्लो प्रश्न पर पढ़ा था। –

+1

क्या आप एक कस्टम dict-like ऑब्जेक्ट को 'अनुरोध' पर पास कर सकते हैं जिसमें एक कस्टम '.items()' है जो हेडर के आदेश को नियंत्रित करता है? यदि 'अनुरोध' उस आदेश को रखता है, तो – user2722968

उत्तर

3

टिप्पणी विस्तार करते हुए, यहाँ एक बहुत, बहुत सरल OrderedHeaders कि requests के साथ खुश हो सकता है:

class OrderedHeaders(object): 

    def __init__(self, *headers): 
     self.headers = headers 

    def items(self): 
     return iter(self.headers) 


oh = OrderedHeaders(('Accept-Charset', 'Foo'), ('Bar', 'Foobar')) 

for k, v in oh.items(): 
    print("%s:%s" % (k, v)) 

यहाँ एक अधिक वर्बोज़ उदाहरण topological sorting का उपयोग करता है जो हेडर को निर्धारित करने के लिए है अन्य शीर्षकों से पहले दिया जाना चाहिए। इसके लिए थोड़ा और कोड की आवश्यकता है, फिर भी आप स्पष्ट रूप से बता सकते हैं कि आपके हेडर के पास एक बार क्या होना चाहिए और बाद में किसी भी अन्य निर्देश की तरह कक्षा का उपयोग करना चाहिए।

import sys 
import toposort 

class OrderedHeaders(dict): 
    # The precedence of headers is determined once. In this example, 
    # 'Accept-Encoding' must be sorted behind 'User-Agent' 
    # (if defined) and 'version' must be sorted behind both 
    # 'Accept-Encoding' and 'Connection' (if defined). 
    PRECEDENCE = toposort.toposort_flatten({'Accept-Encoding': {'User-Agent'}, 
              'version': {'Accept-Encoding', 
                 'Connection'}}) 

    def items(self): 
     s = [] 
     for k, v in dict.items(self): 
      try: 
       prec = self.PRECEDENCE.index(k) 
      except ValueError: 
       # no defined sort for this header, so we put it behind 
       # any other sorted header 
       prec = sys.maxsize 
      s.append((prec, k, v)) 
     return ((k, v) for prec, k, v in sorted(s)) 

# Initialize like a dict 
headers = OrderedHeaders(name='random', Connection='Keep-Alive') 
... 
# Setting more values 
headers['Accept-Encoding'] = 'gzip' 
headers['version'] = '0.1' 
headers['User-Agent'] = 'Firefox' 
... 
# Headers come out of '.items()' like they should 
for k, v in headers.items(): 
    print("%s: %s" % (k, v)) 

प्रिंट

Connection: Keep-Alive 
User-Agent: Firefox 
Accept-Encoding: gzip 
version: 0.1 
name: random 

क्योंकि Connection जरूरतों से पहले version, User-Agent जरूरतों Accept-Encoding से पहले आने के लिए आने के लिए, Accept-Encoding से पहले version और name कोई सॉर्टिंग है आने के लिए की जरूरत है और वजह पिछले डाल है।

आप OrderedHeaders पर किसी भी क्रम में मान सेट कर सकते हैं, सॉर्टिंग .items() में किया जाता है। हालांकि आप यह सुनिश्चित कर सकते हैं कि एक ध्वनि आदेश हमेशा संभव है: यदि आप कोई गलती करते हैं और एक परिपत्र निर्भरता (जैसे 'संस्करण'> 'उपयोगकर्ता-एजेंट'> 'संस्करण') परिभाषित करते हैं, तो आपको "संकलन- पर toposort.CircularDependencyError मिल जाएगा। पहर"।

+0

मेरे द्वारा चलाए जाने वाले परीक्षण, समाधान काम करता है! मैं आपके जवाब के लिए वास्तव में खुश और खुश हूं। मुझे नहीं पता कि क्या कोई और समस्याएं उत्पन्न होती हैं। लेकिन यह एक बहुत ही सरल समाधान और जीवन बचतकर्ता है। मैं सभी परीक्षणों की पुष्टि करने के बाद सही के रूप में चिह्नित करूंगा। –

+0

यहां घर ले जाने का सबक याद रखना है कि पायथन में केवल एक ही वस्तु की परवाह करता है, न कि कोई वस्तु क्या है। 'अनुरोध' किसी ऑब्जेक्ट की अपेक्षा करता है जो '.items()' पर 'dict' जैसा कार्य करता है, और यदि आप वास्तविक 'dict' को पास करते हैं जो आपको मिलता है। हालांकि, जब तक ऑब्जेक्ट व्यवहार करता है तब तक आप कुछ और पास कर सकते हैं। – user2722968

संबंधित मुद्दे