0

I'm trying to use a while loop to iterate through a function in Python which requests a user input, i.e. commitchanges to perform one of two actions, and if the input is not valid after a few attempts to close the program.

If the input is equal to 'y' (Yes) then the program should commit the changes made by the SQL update query, i.e. conn.commit()

If the input is equal to 'n' (No) then the program should not commit the changes and rollback, i.e. conn.rollback()

If the input is anything other than 'y' or 'n' then the program should alert the user that that is not a valid input.

Here's my current function:

def action(inputattempts):
    commitchanges = input()
    if commitchanges.lower() == 'y':
        try:
            conn.commit()
            print ('Table Updated. No. of records updated:', totalupdates)
        except cx_Oracle.DatabaseError as error:
            print(error)
    elif commitchanges.lower() == 'n':
        conn.rollback()
        print ('Rollback - No updates made to table')
    else:
        print ('Not a valid selection - Try again')
        print (inputattempts)

Where the variable totalupdates is a global variable defined later on in the program which counts the number of records affected by the curs.execute SQL query.

I'm then calling the above function in a while loop as follows:

inputattempts = 0
while (inputattempts < 4):
    inputattempts += 1
    action(inputattempts)
print ('FAILED')

Essentially, I'd like the user to have a maximum of 4 attempts at entering a valid input, i.e. 'y' or 'n' before the program aborts if the input is not valid after those attempts. However, if 'y' or 'n' is entered the first time the function is called the program should either commit or rollback and exit the loop.

Currently, I'm having to complete 4 iterations of the while loop regardless of my input. Is there a way I can tweak any of that syntax to exit the loop when the above conditions are met?

Fab Dot
  • 504
  • 1
  • 5
  • 16

4 Answers4

0

Just get the user input outside of actions() and pass it as a parameter:

while inputattempts < 4:
    inputattempts += 1
    commit_changes = input()
    action(inputattempts, commit_changes)

Then after the call to action() you can condition on what you need and break out if appropriate.

0

You can return a value from your function and check over it's returned value to break or not.

def action(inputattempts):
    correct_input = True
    commitchanges = input()
    if commitchanges.lower() == 'y':
        try:
            conn.commit()
            print ('Table Updated. No. of records updated:', totalupdates)
        except cx_Oracle.DatabaseError as error:
            print(error)
    elif commitchanges.lower() == 'n':
        conn.rollback()
        print ('Rollback - No updates made to table')
    else:
        print ('Not a valid selection - Try again')
        print (inputattempts)
        correct_input = False           
    return correct_input

then change your while loop to break the loop when

inputattempts = 0
while (inputattempts < 4):
    inputattempts += 1
    if action(inputattempts):
        break
print ('FAILED')
Eypros
  • 5,370
  • 6
  • 42
  • 75
0

As suggested by @rdimaio:

Your action function returns True if the flow was valid; False otherwise (i.e. invalid user input).

def action(inputattempts):
    commitchanges = input()
    if commitchanges.lower() == 'y':
        try:
            conn.commit()
            print ('Table Updated. No. of records updated:', totalupdates)
        except cx_Oracle.DatabaseError as error:
            print(error)

        return True
    elif commitchanges.lower() == 'n':
        conn.rollback()
        print ('Rollback - No updates made to table')

        return True

    print ('Not a valid selection - Try again')
    print (inputattempts)

    return False

Then, you check whether the flow was valid in your while and break when condition is met:

input_attempts = 0

while input_attempts < 4:
    input_attempts += 1

    if action(input_attempts):
        break

if input_attempts == 4:
    print ('FAILED')
Léopold Houdin
  • 1,515
  • 13
  • 18
0

Have your function return a flag telling whether or not the input was accepted:

def action(inputattempts):
    commitchanges = input()
    if commitchanges.lower() == 'y':
        try:
            conn.commit()
            print ('Table Updated. No. of records updated:', totalupdates)
            return True  # <-- New
        except cx_Oracle.DatabaseError as error:
            print(error)
    elif commitchanges.lower() == 'n':
        conn.rollback()
        print ('Rollback - No updates made to table')
        return True  # <-- New
    else:
        print ('Not a valid selection - Try again')
        print (inputattempts)
        return False  # <-- New

Now in your loop, you can do

inputattempts = 0
while (inputattempts < 4):
    inputattempts += 1
    if action(inputattempts):
        break
print ('FAILED')

where the break simply exists the loop. Also, I imagine that the print of 'FAILED' should only occur if the loop is exited after the 4 attempts, not if the break was reached. This can be achieved using else. Finally, your while loop really only counts, and so a for loop is more appropriate. Consider

for inputattempts in range(4):
    if action(inputattempts):
        break
else:
    print ('FAILED')
jmd_dk
  • 12,125
  • 9
  • 63
  • 94
  • Using the syntax above for the 'while' loop displayed the 'FAILED' message each time an input was entered. Otherwise a very helpful response! – Fab Dot Sep 19 '18 at 12:44