2012-11-23 11 views
7

मैं सॉकेटसेवर का उपयोग करने वाले SimpleXMLRPCServers की एक श्रृंखला का उपयोग करते समय एक httplib.CannotSendRequest अपवाद प्राप्त कर रहा हूं। थ्रेडिंगमिक्सिन।पायथन: httplib.CannotSendRequest जब थ्रेडेड नेक्सिंग किया जाता है SimpleXMLRPCServers

मैं जो एक SimpleXMLRPCServer पर एक समारोह कॉल करने के लिए xmlrpclib का उपयोग करता है एक ग्राहक स्क्रिप्ट है:

मैं 'श्रृंखला' से क्या मतलब पीछा कर रहा है। वह सर्वर, बदले में, एक और SimpleXMLRPCServer को कॉल करता है। मुझे एहसास है कि यह कितना गड़बड़ है, लेकिन अच्छे कारण हैं कि इस वास्तुकला का चयन किया गया है, और मुझे कोई कारण नहीं दिख रहा है कि यह संभव नहीं होना चाहिए।

(testclient)client_script ---calls--> 
    (middleserver)SimpleXMLRPCServer ---calls---> 
     (finalserver)SimpleXMLRPCServer --- does something 
  • अगर मैं SocketServer.ThreadingMixin का उपयोग नहीं करते तो यह समस्या तब उत्पन्न नहीं करता है (लेकिन मैं अनुरोध की जरूरत मल्टी-थ्रेडेड होने के लिए तो यह मदद नहीं करता है।)
  • यदि मैं केवल है सेवाओं का एक स्तर (यानी केवल ग्राहक स्क्रिप्ट कॉलिंग अंतिम सर्वर सीधे) ऐसा नहीं होता है।

मैं इस मुद्दे को नीचे दिए गए सरल परीक्षण कोड में पुन: उत्पन्न करने में सक्षम हूं। वहाँ तीन के टुकड़े कर रहे हैं:

finalserver:

import SocketServer 
import time 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 

class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 

# Create server 
server = AsyncXMLRPCServer(('', 9999), SimpleXMLRPCRequestHandler) 
server.register_introspection_functions() 

def waste_time(): 
    time.sleep(10) 
    return True 

server.register_function(waste_time, 'waste_time') 
server.serve_forever() 

middleserver:

import SocketServer 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 
import xmlrpclib 

class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 

# Create server 
server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler) 
server.register_introspection_functions() 

s = xmlrpclib.ServerProxy('http://localhost:9999') 
def call_waste(): 
    s.waste_time() 
    return True 

server.register_function(call_waste, 'call_waste') 
server.serve_forever() 

testclient:

import xmlrpclib 
s = xmlrpclib.ServerProxy('http://localhost:8888') 
print s.call_waste() 

पुन: पेश करने के लिए निम्न चरणों का उपयोग किया जाना चाहिए:

  1. रन अजगर finalserver.py
  2. रन अजगर middleserver.py
  3. रन अजगर testclient.py
  4. जबकि (3) अभी भी चल रहा है,

काफी अजगर testclient.py का एक और उदाहरण चलाने अक्सर (लगभग हर बार) आपको चरण 4 चलाने की कोशिश करते समय पहली बार त्रुटि मिल जाएगी। दिलचस्प बात यह है कि यदि आप तुरंत चरण (4) चलाने की कोशिश करते हैं तो त्रुटि नहीं होगी।

Traceback (most recent call last): 
    File "testclient.py", line 6, in <module> 
    print s.call_waste() 
    File "/usr/lib64/python2.7/xmlrpclib.py", line 1224, in __call__ 
    return self.__send(self.__name, args) 
    File "/usr/lib64/python2.7/xmlrpclib.py", line 1578, in __request 
    verbose=self.__verbose 
    File "/usr/lib64/python2.7/xmlrpclib.py", line 1264, in request 
    return self.single_request(host, handler, request_body, verbose) 
    File "/usr/lib64/python2.7/xmlrpclib.py", line 1297, in single_request 
    return self.parse_response(response) 
    File "/usr/lib64/python2.7/xmlrpclib.py", line 1473, in parse_response 
    return u.close() 
    File "/usr/lib64/python2.7/xmlrpclib.py", line 793, in close 
    raise Fault(**self._stack[0]) 
xmlrpclib.Fault: <Fault 1: "<class 'httplib.CannotSendRequest'>:"> 

इंटरनेट कहना है कि इस अपवाद getresponse कॉल हस्तक्षेप के बिना httplib.HTTPConnection.request को कई कॉल के कारण हो सकता प्रकट होता है। हालांकि, इंटरनेट SimpleXMLRPCServer के संदर्भ में इस पर चर्चा नहीं करता है। Httplib.CannotSendRequest मुद्दे को हल करने की दिशा में कोई भी पॉइंटर्स की सराहना की जाएगी।

============================================== ===============================================12=64=उत्तर:

ठीक है, मैं थोड़ा बेवकूफ हूँ। मुझे लगता है कि मैं उस समय बहुत लंबे समय तक कोड पर घूर रहा था, जिसने मुझे चेहरे पर घूरने वाले स्पष्ट समाधान को याद किया (वास्तव में, क्योंकि वास्तव में वास्तविक प्रश्न वास्तव में वास्तविक प्रश्न में है।)

असल में, कैनोटसेन्डआरक्वेट होता है जब एक httplib.HTTPConnection एक हस्तक्षेप 'अनुरोध' ऑपरेशन द्वारा बाधित है।प्रत्येक httplib.HTTPConnection.request को .getresponse() कॉल के साथ जोड़ा जाना चाहिए। यदि वह युग्मन किसी अन्य अनुरोध ऑपरेशन द्वारा बाधित है, तो दूसरा अनुरोध CannotSendRequest त्रुटि उत्पन्न करेगा। इसलिए:

connection = httplib.HTTPConnection(...) 
connection.request(...) 
connection.request(...) 

विफल हो जाएगा क्योंकि आपके पास किसी भी प्रतिक्रिया के पहले एक ही कनेक्शन पर दो अनुरोध हैं।

मेरे सवाल का कि वापस लिंक करना:

  1. केवल जगह तीन कार्यक्रमों जहां इस तरह के कनेक्शन किए जा रहे हैं में serverproxy कॉल में हैं।
  2. समस्या केवल थ्रेडिंग के दौरान होती है, इसलिए यह दौड़ की स्थिति की संभावना है।
  3. केवल जगह एक serverproxy कॉल साझा किया जाता है, समाधान तो middleserver.py

में है प्रत्येक थ्रेड बनाने यह खुद serverproxy है के लिए स्पष्ट रूप से है। middleserver की तय संस्करण नीचे है, और यह काम करता है:

import SocketServer 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 
import xmlrpclib 

class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 

# Create server 
server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler) 
server.register_introspection_functions() 

def call_waste(): 
    # Each call to this function creates its own serverproxy. 
    # If this function is called by concurrent threads, each thread 
    # will safely have its own serverproxy. 
    s = xmlrpclib.ServerProxy('http://localhost:9999') 
    s.waste_time() 
    return True 

server.register_function(call_waste, 'call_waste') 
server.serve_forever() 

के बाद से अपनी ही xmlrpclib.serverproxy होने प्रत्येक सूत्र में इस संस्करण परिणाम, वहाँ एक ही उदाहरण serverproxy की लागू का कोई खतरा नहीं HTTPConnection.request अधिक है उत्तराधिकार में एक बार से अधिक। कार्यक्रम इरादे के रूप में काम करते हैं।

परेशानियों के लिए खेद है।

उत्तर

11

ठीक है, मैं थोड़ा बेवकूफ हूँ। मुझे लगता है कि मैं उस समय के लंबे समय तक लंबे समय तक चलने के लिए कोड पर घूर रहा था, जिसने मुझे चेहरे पर घूरने वाले स्पष्ट समाधान को याद किया (काफी सचमुच, क्योंकि जवाब वास्तव में वास्तविक प्रश्न में है।)

असल में, कैनोटसेन्डरक्वैस्ट होता है जब एक httplib.HTTPConnection एक हस्तक्षेप 'अनुरोध' ऑपरेशन द्वारा बाधित है। असल में, प्रत्येक httplib.HTTPConnection.request को .getresponse() कॉल के साथ जोड़ा जाना चाहिए। यदि वह युग्मन किसी अन्य अनुरोध ऑपरेशन द्वारा बाधित है, तो दूसरा अनुरोध CannotSendRequest त्रुटि उत्पन्न करेगा। इसलिए:

connection = httplib.HTTPConnection(...) 
connection.request(...) 
connection.request(...) 

विफल हो जाएगा क्योंकि आपके पास किसी भी प्रतिक्रिया के पहले एक ही कनेक्शन पर दो अनुरोध हैं।

मेरे सवाल का कि वापस लिंक करना:

  1. केवल जगह तीन कार्यक्रमों जहां इस तरह के कनेक्शन किए जा रहे हैं में serverproxy कॉल में हैं।
  2. समस्या केवल थ्रेडिंग के दौरान होती है, इसलिए यह दौड़ की स्थिति की संभावना है।
  3. केवल जगह एक serverproxy कॉल साझा किया जाता है, समाधान तो middleserver.py

में है प्रत्येक थ्रेड बनाने यह खुद serverproxy है के लिए स्पष्ट रूप से है। middleserver की तय संस्करण नीचे है, और यह काम करता है:

import SocketServer 
from SimpleXMLRPCServer import SimpleXMLRPCServer 
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 
import xmlrpclib 

class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass 

# Create server 
server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler) 
server.register_introspection_functions() 

def call_waste(): 
    # Each call to this function creates its own serverproxy. 
    # If this function is called by concurrent threads, each thread 
    # will safely have its own serverproxy. 
    s = xmlrpclib.ServerProxy('http://localhost:9999') 
    s.waste_time() 
    return True 

server.register_function(call_waste, 'call_waste') 
server.serve_forever() 

के बाद से अपनी ही xmlrpclib.serverproxy होने प्रत्येक सूत्र में इस संस्करण परिणाम, वहाँ serverproxy लागू HTTPConnection.request एक बार लगातार अधिक से अधिक का कोई खतरा नहीं है। कार्यक्रम इरादे के रूप में काम करते हैं।

परेशानियों के लिए खेद है।

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