Retry a function

I’m trying to make a function retry if an input isn’t 1 or 2, using the “retry” package. I can’t seem to get it to work. I just started with Python a few days ago and I need urgent help with this. (I’m doing it for a school project due in 11 hours.) What am I doing wrong and is there a better/easier way to retry a function?

from retry import retry

# first value is the exception, tries is the amount of times the function retries, delay is the amount of time between each retry
@retry(ValueError, tries=3, delay=2)
def gooo():
    '''Retry'''

select = int(input("Gibe me number 1 or 2:"))

if select == 1:

digitboy = "Thanks for 1!"

    elif select == 2:

        digitboy = "Thanks for 2!"

    else:

        raise ValueError

        gooo(ValueError)

print(digitboy)

I’m trying to make a function retry if an input isn’t 1 or 2, using the
“retry” package. I can’t seem to get it to work. I just started with
Python a few days ago and I need urgent help with this. (I’m doing it
for a school project due in 11 hours.) What am I doing wrong and is
there a better/easier way to retry a function?

The code below is helpful (essential even) but it would help to also
have a transcript of the errors you get.

Assorted remarks inline below:

from retry import retry

I assume this is what you’re using:

https://pypi.org/project/retry/

first value is the exception, tries is the amount of times the function retries, delay is the amount of time between each retry

@retry(ValueError, tries=3, delay=2)

This looks correct.

def gooo():
‘’‘Retry’’’

This function does not seem to do anything. The purpose of the retry
decorator if to cause gooo to retry if a ValueError occurs within it. If
your function does nothing, there’s nothing to retry.

select = int(input(“Gibe me number 1 or 2:”))
if select == 1:
digitboy = “Thanks for 1!”
elif select == 2:
digitboy = “Thanks for 2!”
else:
raise ValueError
gooo(ValueError)

The indentation above looks wrong. I imagine it should read:

select = int(input("Gibe me number 1 or 2:"))
if select == 1:
    digitboy = "Thanks for 1!"
elif select == 2:
    digitboy = "Thanks for 2!"
else:
    raise ValueError
    gooo(ValueError)

print(digitboy)

I presume this is meant to print digitboy after some retries.

For this to be meaningful, the input and checking of the value should be
inside the gooo() function. That way gooo() can be retried a few
times.

Then there’s the end bit where there’s no 1 or 2:

raise ValueError
gooo(ValueError)

This isn’t right. Exceptions are instances of various exception
classes/types. ValueError is such a class. So the raise probably wants:

raise ValueError("expected 1 or 2, got %s" % select)

to raise a ValueError instance with a meaningful message.

It looks to me like gooo() is meant to ask for the 1 or 2 and return the
value received. So (a) the input() code above needs to be inside the
function and (b) it needs to return that value. it looks like the
digitboy variable is for use outside the function. So your function
might look like:

@retry(ValueError, tries=3, delay=2)
def gooo():
    select = int(input("Gibe me number 1 or 2:"))
    if select == 1 or select == 2:
        return select
    raise ValueError

and outside you’d call gooo() to obtain the value:

value = gooo()

which would do all the retrying. Then use your if-statement to set the
digitboy variable according to the value you get back from gooo().

Cheers,
Cameron Simpson cs@cskk.id.au

Thank you very much. I modified the original code I was trying to get to work because the variables and other stuff was in another language (speaking language not computer). I was using this function to get a 1 or 2 from the user, and then use the 1 or 2 for another function. But, I wanted it to ask for a 1 or 2 again if the user gave something other than 1 or 2. The code I made as an example of what I wanted to do was not correct, and probably didn’t explain exactly what I wanted to do. Thanks for the help.

Thank you very much. I modified the original code I was trying to get
to work because the variables and other stuff was in another language
(speaking language not computer).

Even better :frowning:

I was using this function to get a 1 or 2 from the user, and then use
the 1 or 2 for another function.

Ok, so that pretty much ditates that gooo() just asks for a number and
returns valids one, or raises the exception.

But, I wanted it to ask for a 1 or 2 again if the user gave something
other than 1 or 2. The code I made as an example of what I wanted to do
was not correct, and probably didn’t explain exactly what I wanted to
do. Thanks for the help.

Hopefully things are clearer now. If something remains unclear, come
back and ask.

If you’re new to Python the “@retry” decorator may seem like magic. Of
course, it can’t be. When you write a function like this:

@retry(.....)
def gooo():
    ....

your original gooo() function gets defined just as you would expect.
Then that function (which like everything in Python is just another
object) is handed to the retry() function you imported; that makes a
new function which calls your function. That new function is used in
place of yours. This lets retry() wrap your function in the retry logic.
The “@retry” is a syntactic convenience.

This:

@retry
def gooo():
    ....

is a convenient way to write:

def gooo():
    ....

gooo2 = retry(gooo)
gooo = gooo2

(and discarding the name “gooo2” - that’s there just for clarity).

So retry() is a function which returns a function. It may look like this
inside:

def retry(func):

    # hardwired just for the example
    exception_type = ValueError
    count = 3
    delay = 2

    # define a new function to run the retry logic
    def wrapped_func(*a,**kw):
        tries = count
        while tries > 0:
            tries -= 1
            try:
                return func(*a,**kw)
            except exception_type as e:
                if tries == 0:
                    raise
                warning("got exception %s! retrying...", e)
            if delay > 0:
                sleep(delay)

    # return the new function, ready for use
    return wrapped_func

It gets handed your original gooo() function and defines a new function
to call it in a loop, with exception catching logic inside, as above. It
returns that new function.

The new function’s logic just calls yours in a loop: if it does not
raise an exception, the result is returned as is. Otherwise it catches
the particular exception type you supplied, sleeps briefly and goes
around the loop again. Other exceptions are uncaught and come straight
out, no retry.

Cheers,
Cameron Simpson cs@cskk.id.au

Do you need to use the retry package? If not, what about something like this:

def getinput():
    done = False
    while not done:
        entry = input('Enter 1 or 2: ')
        if entry == 1:
            #do something
            done = True
        elif entry == 2:
            #do something different
            done = True