2011-05-19 14 views
12

मैं पाइथन में एक छोटा यूआरएल अनुवादक इंजन बनाता हूं, और मुझे "टूटी हुई पाइप" त्रुटियों का एक टन दिखाई दे रहा है, और मैं उत्सुक हूं कि बेसएचटीटीपीएस सर्वर कक्षाओं का उपयोग करते समय इसे सबसे अच्छा कैसे फंसाना है। इस पूरी कोड नहीं है, लेकिन आप मैं अब तक क्या कर रही हूं की एक विचार देता है:पायथन बेसएचटीटीपीएसवर, मैं "टूटी हुई पाइप" त्रुटियों को कैसे पकड़/जाल कर सकता हूं?

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 
    import memcache 

    class clientThread(BaseHTTPRequestHandler): 

      def do_GET(self): 
        content = None 
        http_code,response_txt,long_url = \ 
          self.ag_trans_url(self.path,content,'GET') 
        self.http_output(http_code, response_txt, long_url) 
        return 

      def http_output(self,http_code,response_txt,long_url): 
        self.send_response(http_code) 
        self.send_header('Content-type','text/plain') 
        if long_url: 
          self.send_header('Location', long_url) 
        self.end_headers() 
        if response_txt: 
          self.wfile.write(response_txt) 
        return 

     def ag_trans_url(self, orig_short_url, post_action, getpost): 
       short_url = 'http://foo.co' + orig_short_url 

       # fetch it from memcache 
       long_url = mc.get(short_url) 

       # other magic happens to look it up from db if there was nothing 
       # in memcache, etc 
       return (302, None, log_url) 

def populate_memcache() 
     # connect to db, do lots of mc.set() calls 

def main(): 
     populate_memcache() 
     try: 
       port = 8001 
       if len(sys.argv) > 1: 
         port = int(sys.argv[1]) 
       server = HTTPServer(('',port), clientThread) 
       #server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
       print '[',str(datetime.datetime.now()),'] short url processing has begun' 

       server.serve_forever() 
     except KeyboardInterrupt,SystemExit: 
       print '^C received, shutting down server' 
       server.socket.close() 

कोड में ही अच्छा काम करता है, लेकिन जब उत्पादन में त्रुटियों फेंकने के लगभग तुरंत शुरू कर दिया:

Traceback (most recent call last): 
    File "/usr/lib/python2.5/SocketServer.py", line 222, in handle_request 
    self.process_request(request, client_address) 
    File "/usr/lib/python2.5/SocketServer.py", line 241, in process_request 
    self.finish_request(request, client_address) 
    File "/usr/lib/python2.5/SocketServer.py", line 254, in finish_request 
    self.RequestHandlerClass(request, client_address, self) 
    File "/usr/lib/python2.5/SocketServer.py", line 522, in __init__ 
    self.handle() 
    File "/usr/lib/python2.5/BaseHTTPServer.py", line 316, in handle 
    self.handle_one_request() 
    File "/usr/lib/python2.5/BaseHTTPServer.py", line 310, in handle_one_request 
    method() 
    File "/opt/short_url_redirector/shorturl.py", line 38, in do_GET 
    self.http_output(http_code, response_txt, long_url) 
    File "/opt/short_url_redirector/shorturl.py", line 52, in http_output 
    self.send_response(http_code) 
    File "/usr/lib/python2.5/BaseHTTPServer.py", line 370, in send_response 
    self.send_header('Server', self.version_string()) 
    File "/usr/lib/python2.5/BaseHTTPServer.py", line 376, in send_header 
    self.wfile.write("%s: %s\r\n" % (keyword, value)) 
    File "/usr/lib/python2.5/socket.py", line 274, in write 
    self.flush() 
    File "/usr/lib/python2.5/socket.py", line 261, in flush 
    self._sock.sendall(buffer) 
error: (32, 'Broken pipe') 

self.send_header('Location', long_url) 

तो मैं उत्सुक हूँ जहाँ मेरे कोड में फँसाने के लिए प्रयास करने के लिए:

इन त्रुटियों के थोक एक समस्या send_header() विधि बुला होने से रोका जा सके, जहां सभी मैं बाहर लिख रहा हूँ यह है लगता है इसके अलावा IO को छोड़कर आयन ... क्या मैं प्रत्येक self.send_header/self.end_headers/self.wfile.write कॉल के आस-पास कॉल को छोड़कर/कोशिश लिखता हूं?

Traceback (most recent call last): 
    File "/usr/lib/python2.5/SocketServer.py", line 222, in handle_request 
    self.process_request(request, client_address) 
    File "/usr/lib/python2.5/SocketServer.py", line 241, in process_request 
    self.finish_request(request, client_address) 
    File "/usr/lib/python2.5/SocketServer.py", line 254, in finish_request 
    self.RequestHandlerClass(request, client_address, self) 
    File "/usr/lib/python2.5/SocketServer.py", line 522, in __init__ 
    self.handle() 
    File "/usr/lib/python2.5/BaseHTTPServer.py", line 316, in handle 
    self.handle_one_request() 
    File "/usr/lib/python2.5/BaseHTTPServer.py", line 299, in handle_one_request 
    self.raw_requestline = self.rfile.readline() 
    File "/usr/lib/python2.5/socket.py", line 381, in readline 
    data = self._sock.recv(self._rbufsize) 
error: (104, 'Connection reset by peer') 

उत्तर

6

"टूटी पाइप" अपवाद मतलब है कि आपके कोड एक सॉकेट/पाइप के लिए लिखने का प्रयास किया: अन्य त्रुटि मैं समय-समय पर देखते हैं कि यह एक है, लेकिन यकीन है कि जो अपवाद भी इस पकड़ने के लिए देखने के लिए नहीं है जो दूसरा छोर बंद हो गया है। यदि दूसरा अंत एक वेब ब्राउज़र है, तो उपयोगकर्ता अनुरोध को रोक सकता था। आप ट्रेसबैक को अनदेखा कर सकते हैं; यह एक गंभीर समस्या का संकेत नहीं है। अगर आप संदेश को दबाना चाहते हैं, तो आप कोशिश कर सकते हैं ... अपने http_output फ़ंक्शन में सभी कोड के चारों ओर ब्लॉक को छोड़कर, और यदि आप चाहें तो अपवाद लॉग करें।

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

जोड़ें: "सहकर्मी द्वारा कनेक्शन रीसेट" अपवाद का अर्थ है कि आपके कोड ने मृत सॉकेट से पढ़ने की कोशिश की है। यदि आप ट्रेसबैक को दबाना चाहते हैं, तो आपको बेसएचटीटीपीएसर क्लास का विस्तार करना होगा और कोशिश को जोड़ने के लिए handle_one_request विधि को ओवरराइड करना होगा ... ब्लॉक को छोड़कर। एक समय में एक से अधिक अनुरोधों को संसाधित करने के बारे में पहले के सुझाव को लागू करने के लिए आपको किसी भी नए सर्वर वर्ग की आवश्यकता होगी।

+0

धन्यवाद! मैं अभी तक बहु-प्रसंस्करण के बारे में चिंतित नहीं हूं। मैं उत्सुक हूं कि वास्तव में किस जाल के लिए जाल है, क्या यह सिर्फ IOError अपवाद है, या यह कुछ और है? मुझे यह भी संदेह है कि टूटी हुई पाइप त्रुटियां इस तथ्य से आ रही हैं कि यह प्रणाली हैप्रोक्सी फ़ायरवॉल के पीछे रहती है। यह मेरी अगली खोज है। – iandouglas

+1

सॉकेट मॉड्यूल में कार्य सॉकेट को बढ़ाते हैं। आतंक। पायथन 2.6 से शुरू, सॉकेट। आतंक IOError का एक उप-वर्ग है ([सॉकेट मॉड्यूल] का दस्तावेज़ीकरण (http://docs.python.org/library/socket.html))। चूंकि आप 2.5 को लक्षित कर रहे हैं (आपके ट्रेसबैक में फ़ाइल नामों से निर्णय ले रहे हैं), आपको सॉकेट को पकड़ने की आवश्यकता होगी। आतंक। –

9

यह SocketServer में एक बग प्रतीत होता है, इस लिंक Python Bug: 14574

फिक्स देखना (अजगर 2.7 में मेरे लिए काम करता है) SocketServer.StreamRequestHandler खत्म() विधि, कुछ इस तरह ओवरराइड करने के लिए है:

... 
def finish(self,*args,**kw): 
    try: 
    if not self.wfile.closed: 
     self.wfile.flush() 
     self.wfile.close() 
    except socket.error: 
    pass 
    self.rfile.close() 

    #Don't call the base class finish() method as it does the above 
    #return SocketServer.StreamRequestHandler.finish(self) 
+0

फॉलोअप जेसन के लिए धन्यवाद! – iandouglas

+0

मेरा समाधान आपके जैसा ही है, लेकिन 'हैंडल()' विधि में –

3

मेरे आवेदन में, त्रुटि finish() में नहीं हुई, यह handle() में हुआ। यह फिक्स broken pipe त्रुटियों को पकड़ता है:

class MyHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 

    ... 

    def handle(self): 
     try: 
      BaseHTTPServer.BaseHTTPRequestHandler.handle(self) 
     except socket.error: 
      pass 
संबंधित मुद्दे