I want to write to a sample crawler, so it can`t stop when crawling something,then I do like this:
def fun(arg0, arg1):
try:
pass
except Exception, e:
fun(arg0, arg1)
Im really want to know, its a good idea,or how can I do better,thanks
Don't have the function call itself - that will lead to infinite recursion.
Instead, put the code in a loop.
def func():
while there_are_things_to_do():
set_up_for_work()
try:
result = do_something_that_might_fail()
except SomeKnownExeptionType:
handle_the_exception()
continue # Cannot use result, try next work thing
do_something_with(result)
Related
Scraping webpages with Python 3.8, Selenium and BeautifulSoap, I would like to remove or alter some elements. Since not all pages contain the respective elements, I have to catch exceptions:
try:
soup.find('aside', id="post").decompose()
except Exception:
pass
try:
soup.find('footer', id="footer").decompose()
except Exception:
pass
try:
soup.find(class_="myclass")["class"] = ''
except Exception:
pass
There is a lot of repetition in this code (my list of statements is even longer), so I tried to build a block:
try:
soup.find('aside', id="post").decompose()
soup.find('footer', id="footer").decompose()
soup.find(class_="myclass")["class"] = ''
except Exception:
pass
But this isn't what I want to achieve, because if first statement doesn't catch a match, then the following statements aren't evaluated at all.
What's a good, pythonic and elegant way to execute/evaluate all statements? I read, that using pass is bad practice also. Maybe try isn't the correct thing here at all and would be better off using something like isset() in PHP (but in python I don't know the eqivalent)?
Not an ideal solution, but you can decorate functions to ignore exceptions and then use decorated functions instead of originals:
from functools import wraps
def exceptions_ignored(callee):
#wraps(callee)
def _ignore(*args, **kwargs):
try:
return callee(*args, **kwargs)
except Exception:
pass
return _ignore
mydivmod = exceptions_ignored(divmod)
# or define it as
# #exceptions_ignored
# def mydivmod(n, d):
# return divmod(n, d)
mydivmod(5, 0)
I think this should be a bit tricky but somehow feasible, but I need help.
I'd like to execute two functions from within my main() func.
I'd like to be able to catch exceptions from the two separately, but still being able to execute both and get the result of at least one of them if the other raises an exception.
Let's say I have:
def foo():
raise TypeError
def bar():
return 'bar'
If I do (adapted from here):
def multiple_exceptions(flist):
for f in flist:
try:
return f()
except:
continue
def main():
multiple_exceptions([foo, bar])
main()
main() would return 'bar', but I'd like to be able to still throw the exception from foo() after all. This way, I would still have the result of one of my functions and the information on the error occurred in the other.
You can capture and store the exceptions using 'as', e.g.:
try:
raise Exception('I am an error!')
print('The poster messed up error-handling code here.') #should not be displayed
except Exception as Somename:
print(Somename.message)
# you'll see the error message displayed as a normal print result;
# you could do print(stuff, file=sys.stderr) to print it like an error without aborting
print('Code here still works, the function did not abort despite the error above')
...or you can do:
except Exception as Somename:
do_stuff()
raise Somename
Thanks for the comments.
I solved by doing this:
def multiple_exceptions(flist):
exceptions = []
for f in flist:
try:
f()
except Exception as e:
exceptions.append(e.message)
continue
return exceptions
def main():
multiple_exceptions([foo, bar])
error_messages = main() # list of e.messages occurred (to be raised whenever I want)
Then I can raise my exception like e.g. raise Exception(error_messages[0]) (I only care about the first in this case let's say).
I have a requirement to execute multiple Python statements and few of them might fail during execution, even after failing I want the rest of them to be executed.
Currently, I am doing:
try:
wx.StaticBox.Destroy()
wx.CheckBox.Disable()
wx.RadioButton.Enable()
except:
pass
If any one of the statements fails, except will get executed and program exits. But what I need is even though it is failed it should run all three statements.
How can I do this in Python?
Use a for loop over the methods you wish to call, eg:
for f in (wx.StaticBox.Destroy, wx.CheckBox.Disable, wx.RadioButton.Enable):
try:
f()
except Exception:
pass
Note that we're using except Exception here - that's generally much more likely what you want than a bare except.
If an exception occurs during a try block, the rest of the block is skipped. You should use three separate try clauses for your three separate statements.
Added in response to comment:
Since you apparently want to handle many statements, you could use a wrapper method to check for exceptions:
def mytry(functionname):
try:
functionname()
except Exception:
pass
Then call the method with the name of your function as input:
mytry(wx.StaticBox.Destroy)
I would recommend creating a context manager class that suppress any exception and the exceptions to be logged.
Please look at the code below. Would encourage any improvement to it.
import sys
class catch_exception:
def __init__(self, raising=True):
self.raising = raising
def __enter__(self):
pass
def __exit__(self, type, value, traceback):
if issubclass(type, Exception):
self.raising = False
print ("Type: ", type, " Log me to error log file")
return not self.raising
def staticBox_destroy():
print("staticBox_destroy")
raise TypeError("Passing through")
def checkbox_disable():
print("checkbox_disable")
raise ValueError("Passing through")
def radioButton_enable():
print("radioButton_enable")
raise ValueError("Passing through")
if __name__ == "__main__":
with catch_exception() as cm:
staticBox_destroy()
with catch_exception() as cm:
checkbox_disable()
with catch_exception() as cm:
radioButton_enable()
Trying to get the try/except statement working but having problems. This code will take a txt file and copy the file that is in location row 0 to location of row 1. It works however if i change one of the paths to invalid one it generates an error ftplib.error_perm however the except command is not picking up and everything stops. What am i doing wrong? Python 2.4
import csv
import operator
import sys
import os
import shutil
import logging
import ftplib
import tldftp
def docopy(filename):
ftp = tldftp.dev()
inf = csv.reader(open(filename,'r'))
sortedlist = sorted(inf, key=operator.itemgetter(2), reverse=True)
for row in sortedlist:
src = row[0]
dst = row[1]
tldftp.textXfer(ftp, "RETR " + src, dst)
def hmm(haha):
result = docopy(haha);
try:
it = iter(result)
except ftplib.error_perm:
print "Error Getting File"
if __name__ == "__main__":
c = sys.argv[1]
if (c == ''):
raise Exception, "missing first parameter - row"
hmm(c)
The except clause will only catch exceptions that are raised inside of their corresponding try block. Try putting the docopy function call inside of the try block as well:
def hmm(haha):
try:
result = docopy(haha)
it = iter(result)
except ftplib.error_perm:
print "Error Getting File"
The point in the code which raises the error must be inside the try block. In this case, it's likely that the error is raised inside the docopy function, but that isn't enclosed in a try block.
Note that docopy returns None. As such, you will raise an exception when you try to make an iter out of None -- but it won't be a ftplib.error_perm exception, it'll be a TypeError
If you are not sure of what exception will occur, the use the code below, because if especifies for example: except StandardError: and is not that error the exception will not be process.
try:
# some code
except Exception: # Or only except:
print "Error" # Python 3: print("Error")
I know the OP is ancient, but for folks desperate for answers on this question. I had a similar issue, depending on your IDE, if you have a breakpoint on any of the lines with specific exceptions etc, this can conflict and stop try/except executing.
I noticed global exception may not works, e.g. , Ctrl+C when epub.py module perform urllib3 connection trigger KeyboardInterrupt but not able to catch in main thread, the workaround is put my clean up code inside finally, e.g.:
try:
main()
except Exception as e:
clean_up_stuff() #this one never called if keyboard interrupt in module urllib3 thread
finally: #but this work
clean_up_stuff()
This example is generic for Python3.3+, when decorating a generator function, a decorated generator returns successfully, thus not entering the decorators except, the magic happens with yield from f thus wrapping the yieldable within the decorator:
from types import GeneratorType
def generic_exception_catcher(some_kwarg: int = 3):
def catch_errors(func):
def func_wrapper(*args, **kwargs):
try:
f = func(*args, **kwargs)
if type(f) == GeneratorType:
yield from f
else:
return f
except Exception as e:
raise e
return func_wrapper
return catch_errors
Usage:
#generic_exception_catcher(some_kwarg=4)
def test_gen():
for x in range(0, 10):
raise Exception('uhoh')
yield x
for y in test_gen():
print('should catch in the decorator')
When handling exceptions in python, I find myself repeating code quite often. The basic pattern is something of the form:
try:
action_here()
except CommonException1:
Action_always_taken_for_CommonException1()
except CommonException2:
Action_always_taken_for_CommonException2()
except Exception:
Default_action_always_taken()
What I would like to do is to some how abstract this repetitive code out to a function or class. I know one way to do it is to call an exception handling function with the exception object, such as:
try:
action_here()
except Exception as e:
handle_exception(e)
Then in this function determine the exception based on class.
def handle_exception(e):
if type(e) == type(CommonException1()):
Action_always_taken_for_CommonException1()
elif type(e) == type(CommonException2()):
Action_always_taken_for_CommonException2())
else:
Default_action_always_taken()
This, however, feels clunky and inelegant. So my question is, what are some other alternatives to handling repetitive exception handling?
This situation is one of the main use cases for context managers and the with statement:
from __future__ import with_statement # Needed in 2.5, but not in 2.6 or later
from contextlib import contextmanager
#contextmanager
def handle_exceptions():
try:
yield # Body of the with statement effectively runs here
except CommonException1:
Action_always_taken_for_CommonException1()
except CommonException2:
Action_always_taken_for_CommonException2()
except Exception:
Default_action_always_taken()
# Used as follows
with handle_exceptions():
action_here()
If you dislike the repeated if / elseif blocks, you could put your handles in a dict, keyed by type:
handlers = { type(CommonException1()) : Action_always_taken_forCommonException1,
type(CommonException2()) : Action_always_taken_forCommonException2 }
def handle_exception(te):
if te in handlers:
handlers[te]()
else:
Default_action()
Which you could then run with:
try:
action_here()
except Exception as e:
handle_exception(type(e))
In addition: If you find yourself writing these try blocks frequently, then you could write your own context manager (see here). At the action_here() side, your code would then look like this:
with my_error_handling_context():
action_here1()
action_here2()
In this case, the handle_exception code would essentially be your context manager's __exit__ method (which will always get passed any exceptions raised during the with block).
Although a solution using a context manager (as proposed by others) is the most elegant, and would be what I would recommend too, I'd like to point out that your handle_exception function could be written more elegantly by re-raising the exception:
def handle_exception(e):
try:
raise e
except CommonException1:
Action_always_taken_for_CommonException1()
except CommonException2:
Action_always_taken_for_CommonException2()
except Exception:
Default_action_always_taken()