Is this a good way to work with init and exception

Chris Angelico rosuav at gmail.com
Sun Jul 19 08:59:26 EDT 2015


Reordering/interleaving your post to respond to different parts together.

On Sun, Jul 19, 2015 at 8:35 PM, Cecil Westerhof <Cecil at decebal.nl> wrote:
> I am using libturpial to post things on Twitter. But sometimes I get a
> ServiceOverCapacity exception. So I wrote the following code.
>
> ======================================================================
> class InitAlreadyDoneError(Exception):
>     pass

> Is this the correct way to work user defined exceptions, or should I
> also define a default message?

I'd start by looking through the exception hierarchy for something
appropriate to subclass. In this case, you're basically saying "run
init() exactly once, and if you run it a second time, I'll throw back
an error", which probably doesn't have any logical match, so directly
subclassing Exception would be correct. But you might decide that
subclassing ValueError or RuntimeError is more appropriate.

> ##### Functions
> def init(max_tries = 5, wait_time = 60):
>     global _core
>
>     if _core != None:
>         raise InitAlreadyDoneError

This is where I'd add a message, if you want one. But it looks to me
as if there's never going to be any other place that raises this, so
the message would be redundant. InitAlreadyDoneError implies "you
called init() after someone else called init()".

(Side point: It might be a neat courtesy to let people call init
again, or maybe a try_init() that won't error out if already
initialized.)

>     tries = 0
>     while True:
>         try:
>             _core = Core()
>             break
>         except ServiceOverCapacity:
>             tries += 1
>             sys.stderr.write('Tried to init _core it {0} times\n'.format(tries))
>             sys.stderr.flush()
>             if tries >= max_tries:
>                 raise
>             time.sleep(wait_time)
> ======================================================================
>
>
> I use this in the following way:
>     import twitterDecebal
>     twitterDecebal.init()
>
> Because you can not give parameters with an import as far as I can
> see. Is this a good way to do this, or is there a better way?

Parameterized imports aren't possible, correct. What I'd look at here
is a more explicit instantiation. Something like:

import twitterDecebal
twitter = twitterDecebal.twitterDecebal(5, 60)

Especially since it's something that does a ton of network operations
and all sorts of sleeps and timeouts, I would strongly recommend NOT
doing this on import, even if you could. If you don't absolutely
_need_ it to be global, it'd be cleanest to make it a class that you
construct.

ChrisA



More information about the Python-list mailing list