Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #91953 > unrolled thread

Retrying to send message

Started byCecil Westerhof <Cecil@decebal.nl>
First post2015-06-03 14:27 +0200
Last post2015-06-04 07:13 +0200
Articles 9 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  Retrying to send message Cecil Westerhof <Cecil@decebal.nl> - 2015-06-03 14:27 +0200
    Re: Retrying to send message Chris Angelico <rosuav@gmail.com> - 2015-06-03 23:29 +1000
      Re: Retrying to send message Cecil Westerhof <Cecil@decebal.nl> - 2015-06-03 18:15 +0200
        Re: Retrying to send message MRAB <python@mrabarnett.plus.com> - 2015-06-03 19:12 +0100
        Re: Retrying to send message Ethan Furman <ethan@stoneleaf.us> - 2015-06-03 11:28 -0700
        Re: Retrying to send message Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-06-03 21:37 +0100
        Re: Retrying to send message Chris Angelico <rosuav@gmail.com> - 2015-06-04 08:00 +1000
        Re: Retrying to send message Ethan Furman <ethan@stoneleaf.us> - 2015-06-03 16:15 -0700
          Re: Retrying to send message Cecil Westerhof <Cecil@decebal.nl> - 2015-06-04 07:13 +0200

#91953 — Retrying to send message

FromCecil Westerhof <Cecil@decebal.nl>
Date2015-06-03 14:27 +0200
SubjectRetrying to send message
Message-ID<87egltht87.fsf@Equus.decebal.nl>
I am using libturpial to post messages on Twitter. Sometimes I get a
libturpial.exceptions.ServiceOverCapacity.

It is a good idea to try it again then. For this I wrote the following
function:
    def send_message(account_id, message, max_tries, terminate_program):
        error_msg   = 'Something went wrong with: ' + message
        not_send    = True
        tries       = 0
        while not_send:
            try:
                Core().update_status(account_id, message)
            except libturpial.exceptions.ServiceOverCapacity:
                tries += 1
                print('Tried to send it {0} times'.format(tries))
                if tries >= max_tries:
                    terminate_program(error_msg)
                time.sleep(60)
            except:
                terminate_program(error_msg)
            else:
                not_send = False

Is this a reasonable way to implement this, or is another way better?
Well, maybe the timeout should be a parameter also. ;-)


Also the documentation of time.sleep says:
    The actual suspension time may be less than that requested because
    any caught signal will terminate the sleep() following execution
    of that signal’s catching routine.

My program does not much else as sending the message. So I think it is
not necessary to cover for this possibility. Are I assuming to much?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

[toc] | [next] | [standalone]


#91962

FromChris Angelico <rosuav@gmail.com>
Date2015-06-03 23:29 +1000
Message-ID<mailman.108.1433338144.13271.python-list@python.org>
In reply to#91953
On Wed, Jun 3, 2015 at 10:27 PM, Cecil Westerhof <Cecil@decebal.nl> wrote:
>     def send_message(account_id, message, max_tries, terminate_program):
>         error_msg   = 'Something went wrong with: ' + message
>         not_send    = True
>         tries       = 0
>         while not_send:
>             try:
>                 Core().update_status(account_id, message)
>             except libturpial.exceptions.ServiceOverCapacity:
>                 tries += 1
>                 print('Tried to send it {0} times'.format(tries))
>                 if tries >= max_tries:
>                     terminate_program(error_msg)
>                 time.sleep(60)
>             except:
>                 terminate_program(error_msg)
>             else:
>                 not_send = False
>
> Is this a reasonable way to implement this, or is another way better?
> Well, maybe the timeout should be a parameter also. ;-)

I'd skip the not_send flag and do the logic thusly:

while True:
    try:
        update_status as above
        break
    except ServiceOverCapacity:
        as above

And I'd also skip the bare except clause. If you get any sort of
exception, whether it's a bug, a failure from libturpial, a network
error, or anything else, your code will just terminate with a bland
and useless message. Much better to simply let the exception bubble
up.

> Also the documentation of time.sleep says:
>     The actual suspension time may be less than that requested because
>     any caught signal will terminate the sleep() following execution
>     of that signal’s catching routine.
>
> My program does not much else as sending the message. So I think it is
> not necessary to cover for this possibility. Are I assuming to much?

I wouldn't worry too much about a signal cutting your sleep short; it
doesn't look to me as if "exactly sixty seconds" is all that crucial
here. If your program sleeps for 42.645 seconds and then gets woken up
by a signal, and you retry a bit sooner than you otherwise would have,
is it going to break anything? If not, just ignore that possibility.

ChrisA

[toc] | [prev] | [next] | [standalone]


#91976

FromCecil Westerhof <Cecil@decebal.nl>
Date2015-06-03 18:15 +0200
Message-ID<876174ix9n.fsf@Equus.decebal.nl>
In reply to#91962
Op Wednesday 3 Jun 2015 15:29 CEST schreef Chris Angelico:

> On Wed, Jun 3, 2015 at 10:27 PM, Cecil Westerhof <Cecil@decebal.nl> wrote:
>> def send_message(account_id, message, max_tries,
>> terminate_program): error_msg = 'Something went wrong with: ' +
>> message not_send = True tries = 0 while not_send: try:
>> Core().update_status(account_id, message) except
>> libturpial.exceptions.ServiceOverCapacity: tries += 1 print('Tried
>> to send it {0} times'.format(tries)) if tries >= max_tries:
>> terminate_program(error_msg) time.sleep(60) except:
>> terminate_program(error_msg) else: not_send = False
>>
>> Is this a reasonable way to implement this, or is another way
>> better? Well, maybe the timeout should be a parameter also. ;-)
>
> I'd skip the not_send flag and do the logic thusly:
>
> while True:
> try:
> update_status as above
> break
> except ServiceOverCapacity:
> as above

Yes that is much better. I now made it:
    def send_message(account_id, message, max_tries, give_error, wait_time = 60):
        error_msg   = 'Something went wrong with: ' + message
        tries       = 0
        while True:
            try:
                Core().update_status(account_id, message)
                break
            except libturpial.exceptions.ServiceOverCapacity:
                tries += 1
                print('Tried to send it {0} times'.format(tries))
                if tries >= max_tries:
                    give_error(error_msg)
                    return
                time.sleep(wait_time)
            except:
                give_error(error_msg)
                return

> And I'd also skip the bare except clause. If you get any sort of
> exception, whether it's a bug, a failure from libturpial, a network
> error, or anything else, your code will just terminate with a bland
> and useless message. Much better to simply let the exception bubble
> up.

I kept the except. I like to see the message that went wrong. ;-)

Also, in my case give_error terminates the program, but it never hurts
to make functionality generic, so I added return statements. Not
break, because on error you should leave the function. Break would in
this instance do the same, but I find this neater.


>> Also the documentation of time.sleep says:
>> The actual suspension time may be less than that requested because
>> any caught signal will terminate the sleep() following execution
>> of that signal’s catching routine.
>>
>> My program does not much else as sending the message. So I think it
>> is not necessary to cover for this possibility. Are I assuming to
>> much?
>
> I wouldn't worry too much about a signal cutting your sleep short;
> it doesn't look to me as if "exactly sixty seconds" is all that
> crucial here. If your program sleeps for 42.645 seconds and then
> gets woken up by a signal, and you retry a bit sooner than you
> otherwise would have, is it going to break anything? If not, just
> ignore that possibility.

Correct, so I did not assume to much. :-D

Usually I check parameters. But I understood that is not the Python
way. For example a wait_time of 1, or negative is not useful. Also a
max_tries of 10 ** 12 would not be very useful. But I can put the
burden of the problem on the caller of the function?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

[toc] | [prev] | [next] | [standalone]


#91982

FromMRAB <python@mrabarnett.plus.com>
Date2015-06-03 19:12 +0100
Message-ID<mailman.119.1433355137.13271.python-list@python.org>
In reply to#91976
On 2015-06-03 17:15, Cecil Westerhof wrote:
> Op Wednesday 3 Jun 2015 15:29 CEST schreef Chris Angelico:
>
>> On Wed, Jun 3, 2015 at 10:27 PM, Cecil Westerhof <Cecil@decebal.nl> wrote:
>>> def send_message(account_id, message, max_tries,
>>> terminate_program): error_msg = 'Something went wrong with: ' +
>>> message not_send = True tries = 0 while not_send: try:
>>> Core().update_status(account_id, message) except
>>> libturpial.exceptions.ServiceOverCapacity: tries += 1 print('Tried
>>> to send it {0} times'.format(tries)) if tries >= max_tries:
>>> terminate_program(error_msg) time.sleep(60) except:
>>> terminate_program(error_msg) else: not_send = False
>>>
>>> Is this a reasonable way to implement this, or is another way
>>> better? Well, maybe the timeout should be a parameter also. ;-)
>>
>> I'd skip the not_send flag and do the logic thusly:
>>
>> while True:
>> try:
>> update_status as above
>> break
>> except ServiceOverCapacity:
>> as above
>
> Yes that is much better. I now made it:
>      def send_message(account_id, message, max_tries, give_error, wait_time = 60):
>          error_msg   = 'Something went wrong with: ' + message
>          tries       = 0
>          while True:
>              try:
>                  Core().update_status(account_id, message)
>                  break
>              except libturpial.exceptions.ServiceOverCapacity:
>                  tries += 1
>                  print('Tried to send it {0} times'.format(tries))
>                  if tries >= max_tries:
>                      give_error(error_msg)
>                      return
>                  time.sleep(wait_time)
>              except:
>                  give_error(error_msg)
>                  return
>
>> And I'd also skip the bare except clause. If you get any sort of
>> exception, whether it's a bug, a failure from libturpial, a network
>> error, or anything else, your code will just terminate with a bland
>> and useless message. Much better to simply let the exception bubble
>> up.
>
> I kept the except. I like to see the message that went wrong. ;-)
>
You're still swallowing unexpected exceptions.

If any exception apart from ServiceOverCapacity is raised, the bare
except will just call 'give_error' and then return.

If you try to interrupt the program (^C on Windows, ^D on Linux), that'll
also be ignored.

> Also, in my case give_error terminates the program, but it never hurts
> to make functionality generic, so I added return statements. Not
> break, because on error you should leave the function. Break would in
> this instance do the same, but I find this neater.
>
>
>>> Also the documentation of time.sleep says:
>>> The actual suspension time may be less than that requested because
>>> any caught signal will terminate the sleep() following execution
>>> of that signal’s catching routine.
>>>
>>> My program does not much else as sending the message. So I think it
>>> is not necessary to cover for this possibility. Are I assuming to
>>> much?
>>
>> I wouldn't worry too much about a signal cutting your sleep short;
>> it doesn't look to me as if "exactly sixty seconds" is all that
>> crucial here. If your program sleeps for 42.645 seconds and then
>> gets woken up by a signal, and you retry a bit sooner than you
>> otherwise would have, is it going to break anything? If not, just
>> ignore that possibility.
>
> Correct, so I did not assume to much. :-D
>
> Usually I check parameters. But I understood that is not the Python
> way. For example a wait_time of 1, or negative is not useful. Also a
> max_tries of 10 ** 12 would not be very useful. But I can put the
> burden of the problem on the caller of the function?
>

[toc] | [prev] | [next] | [standalone]


#91984

FromEthan Furman <ethan@stoneleaf.us>
Date2015-06-03 11:28 -0700
Message-ID<mailman.120.1433356162.13271.python-list@python.org>
In reply to#91976
On 06/03/2015 09:15 AM, Cecil Westerhof wrote:

> I kept the except. I like to see the message that went wrong. ;-)

That's fine, but then add a `raise` after you print the error so you can see the reason that message failed.

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#91991

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2015-06-03 21:37 +0100
Message-ID<mailman.126.1433363882.13271.python-list@python.org>
In reply to#91976
On 03/06/2015 19:28, Ethan Furman wrote:
> On 06/03/2015 09:15 AM, Cecil Westerhof wrote:
>
>> I kept the except. I like to see the message that went wrong. ;-)
>
> That's fine, but then add a `raise` after you print the error so you can
> see the reason that message failed.
>
> --
> ~Ethan~

Why bother in the first place, especially when you're developing?  Far 
easier to let the exception bubble up, or are we talking cross purposes?

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [next] | [standalone]


#92005

FromChris Angelico <rosuav@gmail.com>
Date2015-06-04 08:00 +1000
Message-ID<mailman.134.1433368816.13271.python-list@python.org>
In reply to#91976
On Thu, Jun 4, 2015 at 2:15 AM, Cecil Westerhof <Cecil@decebal.nl> wrote:
>> And I'd also skip the bare except clause. If you get any sort of
>> exception, whether it's a bug, a failure from libturpial, a network
>> error, or anything else, your code will just terminate with a bland
>> and useless message. Much better to simply let the exception bubble
>> up.
>
> I kept the except. I like to see the message that went wrong. ;-)

In that case, there's an easier way to deal with it: just raise a
different exception, and let them chain. Something like this:

>>> def send_message(msg):
...     try: 1/0
...     except: raise FailedMessageException(msg)
...
>>> class FailedMessageException(Exception): pass
...
>>> send_message("Test")
Traceback (most recent call last):
  File "<stdin>", line 2, in send_message
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in send_message
__main__.FailedMessageException: Test

But I'd still avoid the bare except, and use "except Exception:"
instead. I don't think you want to catch SystemExit in this way, for
instance. So here's how I'd write that code:

>>> def send_message(msg):
...     try: 1/0
...     except Exception as e: raise FailedMessageException(msg) from e
...
>>> send_message("Test")
Traceback (most recent call last):
  File "<stdin>", line 2, in send_message
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in send_message
__main__.FailedMessageException: Test

(Also, the use of "from" here causes a slightly different wording,
which I think is more appropriate. But that's minor.)

You get the report of which message failed, plus you get the complete
traceback from the original exception. Much MUCH more useful.

ChrisA

[toc] | [prev] | [next] | [standalone]


#92012

FromEthan Furman <ethan@stoneleaf.us>
Date2015-06-03 16:15 -0700
Message-ID<mailman.138.1433373373.13271.python-list@python.org>
In reply to#91976
On 06/03/2015 01:37 PM, Mark Lawrence wrote:
> On 03/06/2015 19:28, Ethan Furman wrote:
>> On 06/03/2015 09:15 AM, Cecil Westerhof wrote:
>>
>>> I kept the except. I like to see the message that went wrong. ;-)
>>
>> That's fine, but then add a `raise` after you print the error so you can
>> see the reason that message failed.
>>
>
> Why bother in the first place, especially when you're developing?  Far easier to let the exception bubble up, or are we talking cross purposes?

I think Cecil means he wants to see which twitter message failed to send.  The rest of us would like to also have the error itself displayed.  ;)

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#92029

FromCecil Westerhof <Cecil@decebal.nl>
Date2015-06-04 07:13 +0200
Message-ID<87r3psgioc.fsf@Equus.decebal.nl>
In reply to#92012
Op Thursday 4 Jun 2015 01:15 CEST schreef Ethan Furman:

> On 06/03/2015 01:37 PM, Mark Lawrence wrote:
>> On 03/06/2015 19:28, Ethan Furman wrote:
>>> On 06/03/2015 09:15 AM, Cecil Westerhof wrote:
>>>
>>>> I kept the except. I like to see the message that went wrong. ;-)
>>>
>>> That's fine, but then add a `raise` after you print the error so
>>> you can see the reason that message failed.
>>>
>>
>> Why bother in the first place, especially when you're developing?
>> Far easier to let the exception bubble up, or are we talking cross
>> purposes?
>
> I think Cecil means he wants to see which twitter message failed to
> send. The rest of us would like to also have the error itself
> displayed. ;)

Correct. I display the error in the function I call. I also quit the
program in the function I call. Is the correct thing to do, but if
someone just want to continue after displaying the error, that should
be possible also. That is why I choose to implement it this way.

I should produce some docstring. ;-)

-- 
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