python console menu level looping

Cameron Simpson cs at cskk.id.au
Sun Sep 24 17:11:51 EDT 2017


On 24Sep2017 21:41, Daiyue Weng <daiyueweng at gmail.com> wrote:
>Hi, I tried to make a menu using print statements in Python 3. The code is
>as follows,

One thing, please try to preserve the code indenting in messages. What you 
pasted is all hard against the left side of the screen. I've tried to repair 
it.

>print('insert data into: ')
>data_insert_method = ['new collection', 'existing collection']
>for index, elem in enumerate(data_insert_method):
>  print(index, '-', elem)
>
>while 1:

Remark: we tend to say "while True:", it reads more naturally.

>how_to_insert = input('Choose a method for inserting data: ')
>if how_to_insert:
>  try:
>    how_to_insert = int(how_to_insert)
>    how_to_insert = data_insert_method[how_to_insert]
>    break
>  except ValueError:
>    print('Please type in an integer corresponding to the data insert method')
>    continue
>  except IndexError:
>    print('insert method index out of range')
>    continue

Another remark: it is better to keep try/except around as small a piece of code 
as possible; I'd use two here, one for ValueError around the int() and one for 
IndexError around the [].

>  if how_to_insert == 'new collection':
>    print('Set up collection name : ')
>    db_name_setup = ['manual setup', 'return to the main menu']
>    for index, elem in enumerate(db_name_setup):
>      print(index, '-', elem)
>    while 1:
>      how_to_setup = input('Choose a method for setting up collection: ')
>      if how_to_setup:
>        try:
>          how_to_setup = int(how_to_setup)
>          how_to_setup = db_name_setup[how_to_setup]
>          break
>        except ValueError:
>          print('Please type in an integer corresponding to the collection setup method')
>          continue
>        except IndexError:
>          print('collection setup method index out of range')
>          continue
>        if how_to_setup == 'manual setup':
>          print('Please type in collection name: ')
>        elif how_to_setup == 'return to main menu':
>          print('return to main menu')
>
>It is a 2-level menu, on the 2nd level menu 'new collection', there is an
>option - 'return to the main menu', I am wondering how to loop back to the
>1st level menu, i.e. ['new collection', 'existing collection'],
>whenever 'return to the main menu' is selected.

This is where the lack of indentation in your posted code bites; I've just 
realised I've misread your logic because I misindented your code :-( Your 
"while 1:" is just a loop around the input question, not around the menu 
choices.

I would go with a flag, and use it as your loop condition. Like this:

  running_inner_menu = True
  while running_inner_menu:

So something like this (untested):

  if how_to_insert == 'new collection':
    running_inner_menu = True
    while running_inner_menu:
      print('Set up collection name : ')
      db_name_setup = ['manual setup', 'return to the main menu']
      for index, elem in enumerate(db_name_setup):
        print(index, '-', elem)
      # obtain a valid choice
      while 1:
        how_to_setup = input('Choose a method for setting up collection: ')
        if how_to_setup:
          try:
            how_to_setup = int(how_to_setup)
            how_to_setup = db_name_setup[how_to_setup]
            break
          except ValueError:
            print('Please type in an integer corresponding to the collection 
            setup thod')
            continue
          except IndexError:
            print('collection setup method index out of range')
            continue
      if how_to_setup == 'manual setup':
        print('Please type in collection name: ')
        ... etc ...
      elif how_to_setup == 'return to main menu':
        print('return to main menu')
        running_inner_menu = False

All this depends a little on how your code was originally indented i.e. exactly 
which portions of the code were within each while loop. I've guessed at 
something reasonable, but can see that there's room for different arrangements.

But basicly, keep a state variable indicating that a loop should continue. As a 
piece of terminology, a Boolean (True/False) state variable is often called a 
flag.

This has two advantages:

It means you can turn it off anywhere and next time around the loop will stop, 
whereas doing things directly with continue or break requires "structural" 
control because they only jump out of the innermost loop, and also they act 
right now, preventing other relevant stuff being done.

Also it makes your code more readable and easier to reason able: a loop which 
says "while running_inner_menu:" directly says that this loop controls a 
repeating menu, and that you can get out by changing "running_inner_menu". A 
bare "while 1:" or "while True:" requires the reader to have to scan the code 
to figure out what is being controlled.

Cheers,
Cameron Simpson <cs at cskk.id.au> (formerly cs at zip.com.au)



More information about the Python-list mailing list