Safely run functions without decorators

This is the place for queries that don't fit in any of the other categories.

Safely run functions without decorators

Postby gplayersv » Wed Sep 25, 2013 8:47 am

Hello,

I'm currently writing some tests, I have a setup, teardown, in setup I create users, usergroups, folders, etc... In teardown I delete them.
For one reason or another an exception can be thrown when trying to delete the created objects, so in teardown I have to do something like this:

Code: Select all
try:
    delete_user(u)
except:
    log("Cannot delete user")

try:
    delete_usergroup(ug)
except:
    log("Cannot delete usergroup")

...


I was wondering if there's a nicer way of doing this without all those try/excepts.
Decorators are out of the question because I cannot change the behavior of the delete_user/delete_usergroup/... functions.

Thanks,
Florin
Last edited by Mekire on Wed Sep 25, 2013 11:26 am, edited 1 time in total.
Reason: First post lock
User avatar
gplayersv
 
Posts: 15
Joined: Mon Apr 15, 2013 10:56 am

Re: Safely run functions without decorators

Postby Mekire » Wed Sep 25, 2013 11:33 am

Well naked exceptions are never a good idea. Catch the specific exception you need. Catching all possible exceptions catches things that should never (at least generally) be caught such as keyboard interrupts. I'm not sure exactly what you are doing but it seems fine otherwise. Another solution would be checking if the u and ug variables were valid before calling the functions. I don't know the nature of those variables so I can't really expand on that.

-Mek
User avatar
Mekire
 
Posts: 984
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: Safely run functions without decorators

Postby micseydel » Wed Sep 25, 2013 4:29 pm

I don't think that a blanket except is actually a bad thing here, where it's essential that it not crash, but I would definitely log or print the exceptions in case there's an unexpected one. The idea behind not using a blanket except is that (1) you don't want to hide useful information and (2) an error ridden program should crash hard and early so that it can be diagnosed before having unexpected (and possibly terrible) behavior.

gplayersv: One possible solution to have a bunch of try/except block is a loop with a single try/except inside of it that loops over the functions, their inputs and the log string. Like this
Code: Select all
TESTS = (
    (delete_user, u, "Cannot delete user"),
    (delete_usergroup, ug, "Cannot delete usergroup"),
)

for function, param, log_error in TESTS:
    try:
        function(param)
    except:
        log(log_error)

You'd probably want to be able to handle params instead of a single param, which you can do by replacing the middle element of the tuple with another tuple, and using the argument unpacking syntax or possibly even by using a dictionary and keyword args.
Code: Select all
TESTS = (
    (delete_user, (u,), "Cannot delete user"),
    (delete_usergroup, (ug,), "Cannot delete usergroup"),
)

for function, params, log_error in TESTS:
    try:
        function(*param)
    except:
        log(log_error)

If keyword args are something you want help with, feel free to post back, and we can show you more about that (but you'll probably be able to figure that out with a simple Google search).
Join the #python-forum IRC channel on irc.freenode.net!
User avatar
micseydel
 
Posts: 1130
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

Re: Safely run functions without decorators

Postby gplayersv » Thu Sep 26, 2013 6:46 am

Thanks for the replies!
I realize it's not ok to catch all exceptions but unfortunately the code I'm working with has functions which do this:
Code: Select all
def some_func():
    try:
        do_stuf()
        ...
    except:
        log_something()
        raise

And some of the functions inside those functions also do this, try except block over the whole function code with a raise at the end. But no function has under it's doc what exceptions it throws.
Bad code, no time to refactor :o
Your solution micseydel is what I was looking for. It's simple and pythonic, thanks!
User avatar
gplayersv
 
Posts: 15
Joined: Mon Apr 15, 2013 10:56 am


Return to General Coding Help

Who is online

Users browsing this forum: Bing [Bot] and 2 guests