How to prevent try catching every possible line in python?

前端 未结 6 1765
遥遥无期
遥遥无期 2020-12-14 02:42

I got many lines in a row which may throw an exception, but no matter what, it should still continue the next line. How to do this without individually try catching every si

相关标签:
6条回答
  • 2020-12-14 02:55

    Sometimes, when language misses to support your elegant way of expressing an idea because language development literally failed the last decades, you can only rely on the fact that Python is still a dynamical language which supports the exec statement, which makes the following possible:

    code="""
    for i in range(Square_Size):
        Square[i,i] @= 1
        Square[i+1,i] @= 2
        @dowhatever()
    """
    

    This new operator makes code more pythonic and elegant since you don't need to specify additional if-statemens that guarantee that the index stays in bound or the function does succeed which is totally irrelevant to what we want to express (it just shouldn't stop) here (note: while safe indexing would be possible by creating a class based on the list class, this operator works whenever there should be a try catch) , in Lisp it would be easy to define it in a Lispy way, but it seams to be impossible to define it in an elegant way in Python, but still, here is the little preparser which will make it possible: exec "\n".join([o+"try: "+z.replace("@","")+"\n"+o+"except: pass" if "@" in z else z for z in code.split("\n") for o in ["".join([h for h in z if h==" "])]]) #new <- hackish operator which wraps try catch into line

    The result, assuming that Square was 4x4 and contained only zeros:

    [1 0 0 0]
    [2 1 0 0]
    [0 2 1 0]
    [0 0 2 1]
    

    Relevant: The Sage / Sagemath CAS uses a preparse-function which transforms code before it reaches the Python interpreter. A monkey-patch for that function would be:

    def new_preparse(code,*args, **kwargs):
        code="\n".join([o+"try: "+z.replace("@","")+"\n"+o+"except: pass" if "@" in z else z for z in code.split("\n") for o in ["".join([h for h in z if h==" "])]])
        return preparse(code)
    sage.misc.preparser.preparse=new_preparse
    
    0 讨论(0)
  • 2020-12-14 02:57
    for func in [this_may_cause_an_exception,
                 but_I_still_wanna_run_this,
                 and_this,
                 and_also_this]:
        try:
            func()
        except:
            pass
    

    There are two things to notice here:

    • All actions you want to perform have to represented by callables with the same signature (in the example, callables that take no arguments). If they aren't already, wrap them in small functions, lambda expressions, callable classes, etc.
    • Bare except clauses are a bad idea, but you probably already knew that.

    An alternative approach, that is more flexible, is to use a higher-order function like

    def logging_exceptions(f, *args, **kwargs):
        try:
            f(*args, **kwargs)
        except Exception as e:
            print("Houston, we have a problem: {0}".format(e))
    
    0 讨论(0)
  • 2020-12-14 02:59

    Apart from the answers provided, I think its worth to note that one-line try-except statements have been proposed - see the related PEP 463 with the unfortunate rejection notice:

    """ I want to reject this PEP. I think the proposed syntax is acceptable given the
    desired semantics, although it's still a bit jarring. It's probably no worse than the
    colon used with lambda (which echoes the colon used in a def just like the colon here
    echoes the one in a try/except) and definitely better than the alternatives listed.
    
    But the thing I can't get behind are the motivation and rationale. I don't think that
    e.g. dict.get() would be unnecessary once we have except expressions, and I disagree 
    with the position that EAFP is better than LBYL, or "generally recommended" by Python. 
    (Where do you get that? From the same sources that are so obsessed with DRY they'd rather
    introduce a higher-order-function than repeat one line of code? :-)
    
    This is probably the most you can get out of me as far as a pronouncement. Given that
    the language summit is coming up I'd be happy to dive deeper in my reasons for rejecting
    it there (if there's demand).
    
    I do think that (apart from never explaining those dreadful acronyms :-) this was a 
    well-written and well-researched PEP, and I think you've done a great job moderating the 
    discussion, collecting objections, reviewing alternatives, and everything else that is 
    required to turn a heated debate into a PEP. Well done Chris (and everyone who 
    helped), and good luck with your next PEP! """
    
    0 讨论(0)
  • 2020-12-14 03:05

    You can handle such a task with a decorator:

    import logging
    from functools import wraps
    
    def log_ex(func):
        @wraps(func)
        def _wrapper(*args, **kwargs):
            try:
                func(*args, **kwargs)
            except Exception:
                logging.exception('...')
        return _wrapper
    
    @log_ex
    def this_may_cause_an_exception():
        print 'this_may_cause_an_exception'
        raise RuntimeError()
    
    @log_ex
    def but_i_wanna_run_this():
        print 'but_i_wanna_run_this'
    
    def test():
        this_may_cause_an_exception()
        but_i_wanna_run_this()
    

    Calling the test function will look like (which will show that both functions were executed):

    >>> test()
    this_may_cause_an_exception
    ERROR:root:...
    Traceback (most recent call last):
      File "<stdin>", line 5, in _wrapper
      File "<stdin>", line 4, in my_func
    RuntimeError
    but_i_wanna_run_this
    
    0 讨论(0)
  • 2020-12-14 03:06

    I ran into something similar, and asked a question on SO here. The accepted answer handles logging, and watching for only a specific exception. I ended up with a modified version:

    class Suppressor:
        def __init__(self, exception_type, l=None):
            self._exception_type = exception_type
            self.logger = logging.getLogger('Suppressor')
            if l:
                self.l = l
            else:
                self.l = {}
        def __call__(self, expression):
            try:
                exec expression in self.l
            except self._exception_type as e:
                self.logger.debug('Suppressor: suppressed exception %s with content \'%s\'' % (type(self._exception_type), e))
    

    Usable like so:

    s = Suppressor(yourError, locals()) 
    s(cmdString)
    

    So you could set up a list of commands and use map with the suppressor to run across all of them.

    0 讨论(0)
  • 2020-12-14 03:18
    try:
        this_may_cause_an_exception()
    except:
        logging.exception('An error occured')
    finally:
        but_I_still_wanna_run_this()
        and_this()
        and_also_this()
    

    You can use the finally block of exception handling. It is actually meant for cleanup code though.

    EDIT: I see you said all of the functions can throw exceptions, in which case larsmans' answer is about the cleanest I can think of to catch exception for each function call.

    0 讨论(0)
提交回复
热议问题