Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #94111 > unrolled thread
| Started by | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| First post | 2015-07-19 12:35 +0200 |
| Last post | 2015-07-20 01:27 +0200 |
| Articles | 9 — 2 participants |
Back to article view | Back to comp.lang.python
Is this a good way to work with init and exception Cecil Westerhof <Cecil@decebal.nl> - 2015-07-19 12:35 +0200
Re: Is this a good way to work with init and exception Chris Angelico <rosuav@gmail.com> - 2015-07-19 22:59 +1000
Re: Is this a good way to work with init and exception Cecil Westerhof <Cecil@decebal.nl> - 2015-07-19 18:46 +0200
Re: Is this a good way to work with init and exception Chris Angelico <rosuav@gmail.com> - 2015-07-20 04:11 +1000
Re: Is this a good way to work with init and exception Cecil Westerhof <Cecil@decebal.nl> - 2015-07-19 21:10 +0200
Re: Is this a good way to work with init and exception Chris Angelico <rosuav@gmail.com> - 2015-07-20 07:08 +1000
Re: Is this a good way to work with init and exception Cecil Westerhof <Cecil@decebal.nl> - 2015-07-20 00:19 +0200
Re: Is this a good way to work with init and exception Chris Angelico <rosuav@gmail.com> - 2015-07-20 08:40 +1000
Re: Is this a good way to work with init and exception Cecil Westerhof <Cecil@decebal.nl> - 2015-07-20 01:27 +0200
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2015-07-19 12:35 +0200 |
| Subject | Is this a good way to work with init and exception |
| Message-ID | <87380kzb8b.fsf@Equus.decebal.nl> |
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
##### Functions
def init(max_tries = 5, wait_time = 60):
global _core
if _core != None:
raise InitAlreadyDoneError
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)
======================================================================
Is this the correct way to work user defined exceptions, or should I
also define a default message?
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?
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-07-19 22:59 +1000 |
| Message-ID | <mailman.711.1437310769.3674.python-list@python.org> |
| In reply to | #94111 |
Reordering/interleaving your post to respond to different parts together.
On Sun, Jul 19, 2015 at 8:35 PM, Cecil Westerhof <Cecil@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
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2015-07-19 18:46 +0200 |
| Message-ID | <87r3o4xfhx.fsf@Equus.decebal.nl> |
| In reply to | #94114 |
On Sunday 19 Jul 2015 14:59 CEST, Chris Angelico wrote:
> Reordering/interleaving your post to respond to different parts
> together.
>
> On Sun, Jul 19, 2015 at 8:35 PM, Cecil Westerhof <Cecil@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.
Subclassing ValueError or RuntimeError looks wrong to me.
>> ##### 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()".
I thought so, but just wanted to be sure. ;-)
> (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.)
I changed it to:
========================================================================
def init(max_tries = 5, wait_time = 60, reinit_allowed = False):
global _core
if (_core != None) and not reinit_allowed:
raise InitAlreadyDoneError
========================================================================
>> 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)
I worked with default values, because I thought that would be a good
idea. I should remove the default values?
> 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.
In principal I only mend that before you use the twitter functions you
need to do the init. (And because of the ton of functions I wanted a
reinit to be an error.) In my case it is exactly below the import.
Because I use it in a script and except one situation _core is always
used. So I thought it to be more clear.
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-07-20 04:11 +1000 |
| Message-ID | <mailman.733.1437329515.3674.python-list@python.org> |
| In reply to | #94135 |
On Mon, Jul 20, 2015 at 2:46 AM, Cecil Westerhof <Cecil@decebal.nl> wrote: > On Sunday 19 Jul 2015 14:59 CEST, Chris Angelico wrote: > >> Reordering/interleaving your post to respond to different parts >> together. >> >> On Sun, Jul 19, 2015 at 8:35 PM, Cecil Westerhof <Cecil@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. > > Subclassing ValueError or RuntimeError looks wrong to me. Sure. Like I said, directly subclassing Exception seemed the most logical route. Just threw that out there as a possibility. >> (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.) > > I changed it to: > ======================================================================== > def init(max_tries = 5, wait_time = 60, reinit_allowed = False): > global _core > > if (_core != None) and not reinit_allowed: > raise InitAlreadyDoneError > ======================================================================== That works, too! >>> 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) > > I worked with default values, because I thought that would be a good > idea. I should remove the default values? No no, the default values are good. I just gave an example that didn't use them, as that's where you actually need the call. If you're always going to use the defaults, well, there's not a lot of point having the function. But if you often use the defaults (or one of them), and occasionally override it, then what you have is good design. >> 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. > > In principal I only mend that before you use the twitter functions you > need to do the init. (And because of the ton of functions I wanted a > reinit to be an error.) In my case it is exactly below the import. > Because I use it in a script and except one situation _core is always > used. So I thought it to be more clear. I think it's fine, then. As long as it makes absolutely no sense to have two separately-initialized twitter connections, and as long as it's okay for two separate modules to both import this and to then share state, then what you have is fine. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2015-07-19 21:10 +0200 |
| Message-ID | <87io9gx8tb.fsf@Equus.decebal.nl> |
| In reply to | #94144 |
On Sunday 19 Jul 2015 20:11 CEST, Chris Angelico wrote: >>> 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) >> >> I worked with default values, because I thought that would be a >> good idea. I should remove the default values? > > No no, the default values are good. I just gave an example that > didn't use them, as that's where you actually need the call. If > you're always going to use the defaults, well, there's not a lot of > point having the function. But if you often use the defaults (or one > of them), and occasionally override it, then what you have is good > design. In my case I think the defaults are good. (But I do not know how I will use the function in the future. ;-) ) But I want to share it on GitHub and it would be possible that for someone else my defaults are not correct and then it is nice when they can be overridden. > I think it's fine, then. As long as it makes absolutely no sense to > have two separately-initialized twitter connections, and as long as > it's okay for two separate modules to both import this and to then > share state, then what you have is fine. I do not see myself doing this, but I like to know ‘everything’. When I have a program with two different modules that both import this, they would get in each-others way? How? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-07-20 07:08 +1000 |
| Message-ID | <mailman.743.1437340103.3674.python-list@python.org> |
| In reply to | #94153 |
On Mon, Jul 20, 2015 at 5:10 AM, Cecil Westerhof <Cecil@decebal.nl> wrote: >> I think it's fine, then. As long as it makes absolutely no sense to >> have two separately-initialized twitter connections, and as long as >> it's okay for two separate modules to both import this and to then >> share state, then what you have is fine. > > I do not see myself doing this, but I like to know ‘everything’. When > I have a program with two different modules that both import this, > they would get in each-others way? How? If two modules import the same module, they get two references to that same module, not two separate module instances. Since your parameters appear only to affect the initialization itself, this is not likely to be a problem (it's not like you'll need to authenticate with two different sets of credentials, for instance), but it will mean that the second one will import an already-initialized module. That's why I suggested the try_init function which would quietly return an immediate success if the module had already been initialized. But if this isn't going to be an issue, then your code's fine. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2015-07-20 00:19 +0200 |
| Message-ID | <87615fyem2.fsf@Equus.decebal.nl> |
| In reply to | #94163 |
On Sunday 19 Jul 2015 23:08 CEST, Chris Angelico wrote:
> On Mon, Jul 20, 2015 at 5:10 AM, Cecil Westerhof <Cecil@decebal.nl> wrote:
>>> I think it's fine, then. As long as it makes absolutely no sense
>>> to have two separately-initialized twitter connections, and as
>>> long as it's okay for two separate modules to both import this and
>>> to then share state, then what you have is fine.
>>
>> I do not see myself doing this, but I like to know ‘everything’.
>> When I have a program with two different modules that both import
>> this, they would get in each-others way? How?
>
> If two modules import the same module, they get two references to
> that same module, not two separate module instances. Since your
> parameters appear only to affect the initialization itself, this is
> not likely to be a problem (it's not like you'll need to
> authenticate with two different sets of credentials, for instance),
> but it will mean that the second one will import an
> already-initialized module. That's why I suggested the try_init
> function which would quietly return an immediate success if the
> module had already been initialized. But if this isn't going to be
> an issue, then your code's fine.
Good to know. I would expect two different instances.
I agree that in my case it would not be a problem, but I put the code
on GitHub:
https://github.com/CecilWesterhof/PythonLibrary/blob/master/twitterDecebal.py
I should do my best to circumvent nasty surprises for users of the
code. Someone else could use several Twitter accounts at the same
time. Is there a way to do this?
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-07-20 08:40 +1000 |
| Message-ID | <mailman.748.1437345644.3674.python-list@python.org> |
| In reply to | #94169 |
On Mon, Jul 20, 2015 at 8:19 AM, Cecil Westerhof <Cecil@decebal.nl> wrote: >> If two modules import the same module, they get two references to >> that same module, not two separate module instances. Since your >> parameters appear only to affect the initialization itself, this is >> not likely to be a problem (it's not like you'll need to >> authenticate with two different sets of credentials, for instance), >> but it will mean that the second one will import an >> already-initialized module. That's why I suggested the try_init >> function which would quietly return an immediate success if the >> module had already been initialized. But if this isn't going to be >> an issue, then your code's fine. > > Good to know. I would expect two different instances. > > I agree that in my case it would not be a problem, but I put the code > on GitHub: > https://github.com/CecilWesterhof/PythonLibrary/blob/master/twitterDecebal.py > I should do my best to circumvent nasty surprises for users of the > code. Someone else could use several Twitter accounts at the same > time. Is there a way to do this? Does the instantiation of Core() involve authentication? Is it possible to call Core() more than once and use different accounts? Your send_message() takes an account identifier, so it might be you don't need separate accounts. But if, just very occasionally, you do need multiple, here's a possible design style: Have init() return the Core as well as stashing it in _core, and then have send_message() take an optional keyword argument (in 3.x, keyword-only) to choose a different core. That way, it'll by default use the most recently initialized core, but you can create multiple and manage them yourself if you so choose. (Obviously you'd use reinit_allowed=True for all the initializations.) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Cecil Westerhof <Cecil@decebal.nl> |
|---|---|
| Date | 2015-07-20 01:27 +0200 |
| Message-ID | <87vbdfwwwd.fsf@Equus.decebal.nl> |
| In reply to | #94171 |
On Monday 20 Jul 2015 00:40 CEST, Chris Angelico wrote: > On Mon, Jul 20, 2015 at 8:19 AM, Cecil Westerhof <Cecil@decebal.nl> wrote: >>> If two modules import the same module, they get two references to >>> that same module, not two separate module instances. Since your >>> parameters appear only to affect the initialization itself, this >>> is not likely to be a problem (it's not like you'll need to >>> authenticate with two different sets of credentials, for >>> instance), but it will mean that the second one will import an >>> already-initialized module. That's why I suggested the try_init >>> function which would quietly return an immediate success if the >>> module had already been initialized. But if this isn't going to be >>> an issue, then your code's fine. >> >> Good to know. I would expect two different instances. >> >> I agree that in my case it would not be a problem, but I put the >> code on GitHub: >> https://github.com/CecilWesterhof/PythonLibrary/blob/master/twitterDecebal.py >> I should do my best to circumvent nasty surprises for users of the >> code. Someone else could use several Twitter accounts at the same >> time. Is there a way to do this? > > Does the instantiation of Core() involve authentication? Is it > possible to call Core() more than once and use different accounts? > Your send_message() takes an account identifier, so it might be you > don't need separate accounts. But if, just very occasionally, you do > need multiple, here's a possible design style: Have init() return > the Core as well as stashing it in _core, and then have > send_message() take an optional keyword argument (in 3.x, > keyword-only) to choose a different core. That way, it'll by default > use the most recently initialized core, but you can create multiple > and manage them yourself if you so choose. (Obviously you'd use > reinit_allowed=True for all the initializations.) You are right: core is a general initialisation, so in this case nothing to worry about. :-D When I write something where it could make a difference, I should use your tip. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web