2009-03-20 36 views
51

Tôi có đoạn code sau đây để làm một postback đến một URL từ xa:Tôi cần xử lý lỗi nào/ngoại lệ với urllib2.Request/urlopen?

request = urllib2.Request('http://www.example.com', postBackData, { 'User-Agent' : 'My User Agent' }) 

try: 
    response = urllib2.urlopen(request) 
except urllib2.HTTPError, e: 
    checksLogger.error('HTTPError = ' + str(e.code)) 
except urllib2.URLError, e: 
    checksLogger.error('URLError = ' + str(e.reason)) 
except httplib.HTTPException, e: 
    checksLogger.error('HTTPException') 

Các postBackData được tạo ra sử dụng một từ điển được mã hóa sử dụng urllib.urlencode. checksLogger là một trình ghi nhật ký sử dụng logging.

Tôi gặp sự cố khi mã này chạy khi máy chủ từ xa ngừng hoạt động và mã thoát (đây là trên máy chủ của khách hàng vì vậy tôi không biết kết xuất/lỗi ngăn thoát xuất hiện tại thời điểm này). Tôi giả định điều này là do có một ngoại lệ và/hoặc lỗi không được xử lý. Vì vậy, có bất kỳ trường hợp ngoại lệ khác có thể được kích hoạt mà tôi không xử lý ở trên?

Trả lời

50

Thêm xử lý ngoại lệ chung:

request = urllib2.Request('http://www.example.com', postBackData, { 'User-Agent' : 'My User Agent' }) 

try: 
    response = urllib2.urlopen(request) 
except urllib2.HTTPError, e: 
    checksLogger.error('HTTPError = ' + str(e.code)) 
except urllib2.URLError, e: 
    checksLogger.error('URLError = ' + str(e.reason)) 
except httplib.HTTPException, e: 
    checksLogger.error('HTTPException') 
except Exception: 
    import traceback 
    checksLogger.error('generic exception: ' + traceback.format_exc()) 
+0

là 'checksLogger.error' một hàm do người dùng định nghĩa trong ví dụ của bạn? – codingknob

+1

@ algotr8der: vâng, nó chỉ là copy'n'paste của đăng nhập trong câu hỏi – vartec

+0

okay tuyệt vời. Cảm ơn bạn. – codingknob

1

Bạn có thể bắt tất cả các trường hợp ngoại lệ và đăng nhập gì của bị bắt:

import sys 
import traceback 
def formatExceptionInfo(maxTBlevel=5): 
    cla, exc, trbk = sys.exc_info() 
    excName = cla.__name__ 
    try: 
     excArgs = exc.__dict__["args"] 
    except KeyError: 
     excArgs = "<no args>" 
    excTb = traceback.format_tb(trbk, maxTBlevel) 
    return (excName, excArgs, excTb) 
try: 
    x = x + 1 
except: 
    print formatExceptionInfo() 

(Mã số từ http://www.linuxjournal.com/article/5821)

Cũng đọc documentation on sys.exc_info.

+0

Tốt hơn để sử dụng "ngoại trừ ngoại lệ:", do đó bạn không gặp lỗi sẽ gây ra sự cố trong trình xử lý ngoại trừ của bạn. –

+0

Tốt hơn là không bắt ngoại lệ nếu bạn chỉ đăng nhập chúng - xem câu trả lời của tôi. –

+0

@ S.Lott: cảm ơn, đó là một mẹo tôi không quen thuộc với –

15

Từ mục nhập số docs pageurlopen, có vẻ như bạn chỉ cần bắt URLError. Nếu bạn thực sự muốn bảo vệ cược của bạn chống lại các vấn đề trong mã urllib, bạn cũng có thể bắt giữ Exception dưới dạng hình thức thu gọn. Làm không phải chỉ except:, vì điều đó cũng sẽ bắt được SystemExitKeyboardInterrupt.

Chỉnh sửa: Điều tôi muốn nói là, bạn đang gặp phải lỗi mà nó phải ném. Nếu nó ném một cái gì đó khác, nó có thể là do mã urllib không bắt một cái gì đó mà nó nên đã bị bắt và bọc trong một URLError. Ngay cả các stdlib có xu hướng bỏ lỡ những điều đơn giản như AttributeError. Việc bắt giữ số Exception làm giảm thời gian (và ghi lại nội dung bị bắt) sẽ giúp bạn tìm ra điều gì đang xảy ra mà không bị mắc kẹt SystemExitKeyboardInterrupt.

+1

+1 cho liên kết tới tài liệu và lời khuyên rõ ràng về ngoại lệ –

+3

+1 để cho tôi biết sự khác biệt giữa ngoại trừ: ngoại trừ Ngoại lệ (ít nhất một trong số đó) . – hyperboreean

+0

Có ngoại trừ urllib2.URLError, e: chưa bắt URLError? – DavidM

13
$ grep "raise" /usr/lib64/python/urllib2.py 
IOError); for HTTP errors, raises an HTTPError, which can also be 
     raise AttributeError, attr 
       raise ValueError, "unknown url type: %s" % self.__original 
     # XXX raise an exception if no one else should try to handle 
     raise HTTPError(req.get_full_url(), code, msg, hdrs, fp) 
     perform the redirect. Otherwise, raise HTTPError if no-one 
      raise HTTPError(req.get_full_url(), code, msg, headers, fp) 
       raise HTTPError(req.get_full_url(), code, 
      raise HTTPError(req.get_full_url(), 401, "digest auth failed", 
       raise ValueError("AbstractDigestAuthHandler doesn't know " 
      raise URLError('no host given') 
      raise URLError('no host given') 
      raise URLError(err) 
     raise URLError('unknown url type: %s' % type) 
     raise URLError('file not on local host') 
      raise IOError, ('ftp error', 'no host given') 
      raise URLError(msg) 
      raise IOError, ('ftp error', msg), sys.exc_info()[2] 
      raise GopherError('no host given') 

Ngoài ra còn có khả năng ngoại lệ trong phụ thuộc urllib2 hoặc ngoại lệ do lỗi chính hãng gây ra.

Bạn nên ghi nhật ký tất cả các trường hợp ngoại lệ chưa lưu trong một tệp qua tùy chỉnh sys.excepthook. Quy tắc quan trọng của ngón tay cái ở đây là không bao giờ bắt ngoại lệ mà bạn không định sửa đổi và ghi nhật ký không phải là chỉnh sửa. Vì vậy, không bắt chúng chỉ để đăng nhập chúng.

0

tôi bắt:

httplib.HTTPException
urllib2.HTTPError
urllib2.URLError

Tôi tin này bao gồm tất cả mọi thứ bao gồm cả lỗi socket.

+2

'urllib2.HTTPError' là một phân lớp của' urllib2.URLError', vì vậy hãy bắt thứ hai là đủ – pictuga

+1

không ai trong số các catch.error bắt –