Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder1.news.weretis.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.freenet.ag!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'explicitly': 0.05; 'layers': 0.07; 'python3': 0.07; 'skip:u 30': 0.07; 'ugly': 0.07; 'derived': 0.09; 'except:': 0.09; 'exception,': 0.09; 'msg': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'try:': 0.09; 'subject:question': 0.10; 'python': 0.11; 'jan': 0.12; 'project,': 0.12; 'errno': 0.16; 'exception:': 0.16; 'exceptions,': 0.16; 'fetch': 0.16; 'handling,': 0.16; 'nightmare': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'recently.': 0.16; 'reedy': 0.16; 'subject:exception': 0.16; 'subject:handling': 0.16; 'timeout': 0.16; 'urllib': 0.16; 'exception': 0.16; 'do,': 0.16; 'wrote:': 0.18; 'code.': 0.18; 'do.': 0.18; 'library': 0.18; 'bit': 0.19; 'trying': 0.19; 'reset': 0.22; 'header:User-Agent:1': 0.23; 'error': 0.23; 'large,': 0.24; 'fine': 0.24; 'looks': 0.24; 'handling': 0.26; 'skip:" 30': 0.26; 'header:X-Complaints-To:1': 0.27; 'header:In- Reply-To:1': 0.27; 'tried': 0.27; 'am,': 0.29; 'field,': 0.30; 'statement': 0.30; 'skip:( 20': 0.30; 'program,': 0.31; 'bad.': 0.31; 'catching': 0.31; 'directly,': 0.31; 'exceptions': 0.31; 'seemingly': 0.31; 'class': 0.32; 'there.': 0.32; 'probably': 0.32; 'checking': 0.33; 'totally': 0.33; 'could': 0.34; 'common': 0.35; 'connection': 0.35; 'except': 0.35; 'something': 0.35; 'requirement': 0.35; 'but': 0.35; 'there': 0.35; 'really': 0.36; 'curious': 0.36; 'interact': 0.36; 'possible': 0.36; 'hi,': 0.36; 'should': 0.36; 'so,': 0.37; 'too': 0.37; 'level': 0.37; 'sometimes': 0.38; 'to:addr:python-list': 0.38; '(from': 0.39; 'itself': 0.39; 'to:addr:python.org': 0.39; 'either': 0.39; 'received:org': 0.40; 'how': 0.40; 'skip:u 10': 0.60; 'catch': 0.60; 'simple,': 0.60; 'most': 0.60; 'received:173': 0.61; 'simple': 0.61; 'first': 0.61; 'times': 0.62; 'email addr:gmail.com': 0.63; 'field': 0.63; 'skip:n 10': 0.64; 'became': 0.64; 'grab': 0.64; 'more': 0.64; 'different': 0.65; 'details': 0.65; 'funny': 0.74; 'fails,': 0.84; 'received:fios.verizon.net': 0.84; 'from.': 0.93 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Terry Jan Reedy Subject: Re: newbie question about confusing exception handling in urllib Date: Tue, 09 Apr 2013 10:19:08 -0400 References: <1ae3261b-078d-4362-abff-ea4471addd6a@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Gmane-NNTP-Posting-Host: pool-173-75-251-66.phlapa.fios.verizon.net User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130328 Thunderbird/17.0.5 In-Reply-To: <1ae3261b-078d-4362-abff-ea4471addd6a@googlegroups.com> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 65 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1365517159 news.xs4all.nl 6869 [2001:888:2000:d::a6]:52654 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:43176 On 4/9/2013 7:41 AM, cabbar@gmail.com wrote: > Hi, > > I have been using Java/Perl professionally for many years and have been trying to learn python3 recently. As my first program, I tried writing a class for a small project, and I am having really hard time understanding exception handling in urllib and in python in general... > Basically, what I want to do is very simple, Very funny ;-). What you are trying to do, as your first project, is interact with the large, multi-layered, non=deterministic monster known as Internet, with timeout handling, through multiple layers of library code. When it comes to exception handling, this is about the most complex thing you can do. > try to fetch something "tryurllib.request.urlopen(request)", and: > - If request times out or connection is reset, re-try n times > - If it fails, return an error > - If it works return the content. > > But, this simple requirement became a nightmare for me. I am really confused about how I should be checking this because: > - When connection times out, I sometimes get URLException with "reason" field set to socket.timeout, and checking (isinstance(exception.reason, socket.timeout)) works fine > - But sometimes I get socket.timeout exception directly, and it has no "reason" field, so above statement fails, since there is no reason field there. If you are curious why the different exceptions for seemingly the same problem, you can look at the printed traceback to see where the different exceptions come from. Either don't catch the exceptions, re-raise them, or explicitly grab the traceback (from exc_info, I believe) > - Connection reset is a totally different exception > - Not to mention, some exceptions have msg / reason / errno fields but some don't, so there is no way of knowing exception details unless you check them one by one. The only common thing I could was to find call __str__()? The system is probably a bit more ragged then it might be if completely re-designed from scratch. > - Since, there are too many possible exceptions, you need to catch BaseException (I received URLError, socket.timeout, ConnectionRefusedError, ConnectionResetError, BadStatusLine, and none share a common parent). And, catching the top level exception is not a good thing. You are right, catching BaseException is bad. In particular, it will catch KeyboardInterrupt from a user trying to stop the process. It is also unnecessary as all the exceptions you want to catch are derived from Exception, which itself is derived from BaseException. > So, I ended up writing the following, but from everything I know, this looks really ugly and wrong??? > > try: > response = urllib.request.urlopen(request) > content = response.read() > except BaseException as ue: except Exception as ue: > if (isinstance(ue, socket.timeout) or (hasattr(ue, "reason") and isinstance(ue.reason, socket.timeout)) or isinstance(ue, ConnectionResetError)): > print("REQUEST TIMED OUT") > > or, something like: > > except: except Exception: > (a1,a2,a3) = sys.exc_info() > errorString = a2.__str__() > if ((errorString.find("Connection reset by peer") >= 0) or (errorString.find("error timed out") >= 0)): -- Terry Jan Reedy