Python clean way to wrap individual statements in a try except block

前端 未结 4 1407
情话喂你
情话喂你 2021-01-17 21:14

I\'m currently doing some Python automation of Excel with com. It\'s fully functional, and does what I want, but I\'ve discovered something surprising. Sometimes, some of th

4条回答
  •  囚心锁ツ
    2021-01-17 21:27

    Exceptions never happen "for no apparent reason". There is always a reason and that reason needs to be fixed. Otherwise, your program will start to produce "random" data where "random" is at the mercy of the bug that you're hiding.

    But of course, you need a solution for your problem. Here is my suggestion:

    1. Create a wrapper class that implements all the methods that you need and delegates them to the real Excel instance.

    2. Add a decorator before each method which wraps the method in a try except block and log the exception. Never swallow exceptions

    Now the code works for your customer which buys you some time to find out the cause of the problem. My guess is that a) Excel doesn't produce a useful error message or b) the wrapper code swallows the real exception leaving you in the dark or c) the Excel method returns an error code (like "false" for "failed") and you need to call another Excel method to determine what the cause of the problem is.

    [EDIT] Based on the comment below which boil down to "My boss doesn't care and there is nothing I can do": You're missing a crucial point: It's your bosses duty to make the decision but it your duty to give her a list of options along with pros/cons so that she can make a sound decision. Just sitting there saying "I can't do anything" will get you into the trouble that you're trying to avoid.

    Example:

    Solution 1: Ignore the errors

    Pro: Least amount of work Con: There is a chance that the resulting data is wrong or random. If important business decisions are based on it, there is a high risk that those decisions will be wrong.

    Solution 2: Log the errors

    Pro: Little amount of work, users can start to use the results quickly, buys time to figure out the source of the problem Con: "If you can't fix it today, what makes you think you will have time to fix it tomorrow?" Also, it might take you a long time to find the source of the problem because you're no expert

    Solution 3: Ask an expert

    Find an expert in the field and help him/her have a look/improve the solution.

    Pro: Will get a solution much more quickly than learning the ins and outs of COM yourself Con: Expensive but high chance of success. Will also find problems that we don't even know about.

    ...

    I think you see the pattern. Bosses make wrong decisions because we (willingly) let them. Any boss in the world is happy for hard facts and input when they have to make a decision (well, those who don't shouldn't be bosses, so this is a surefire way to know when to start looking for a new job).

    If you select solution #2, go for the wrapper approach. See the docs how to write a decorator (example from IBM). It's just a few minutes of work to wrap all the methods and it will give you something to work with.

    The next step is to create a smaller example which sometimes fails and then post specific questions about Python, Excel and the COM wrapper here to figure out the reason for the problems.

    [EDIT2] Here is some code that wraps the "dangerous" parts in a helper class and makes updating the styles more simple:

    class BorderHelper(object):
        def __init__(self, excel):
            self.excel = excel
    
        def set( type, LineStyle = None, Weight = None, Color = None ):
            border = self.excel.Selection.Borders( type )
    
            try:
                if LineStyle is not None:
                    border.LineStyle = LineStyle
            except:
                pass # Ignore if a style can't be set
    
            try:
                if Weight is not None:
                    border.Weight = Weight
            except:
                pass # Ignore if a style can't be set
    
            try:
                if Color is not None:
                    border.Color = Color
            except:
                pass # Ignore if a style can't be set
    

    Usage:

        borders = BorderHelper( excel )
    
        borders.set( xlDiagonalDown, LineStyle = xlNone )
        borders.set( xlDiagonalUp, LineStyle = xlNone )
        borders.set( xlEdgeLeft, LineStyle = xlContinuous, Weight = xlThin, Color = xlAutomatic )
        ...
    

提交回复
热议问题