Okay, continuing on with my little System access project I've been working on. Now I've gotten three different Python files in this Project. I'm using a main menu .py to offer option for the user to select from. Each option then opens one of the other two .py files and runs them respectively. Now, each of these files i've created run fine on their own. But when I launch one of the files from within another, I seen to be getting alot of "Global name 'Whatever' is not defined, and terminates the program. Perhaps all the functions aren't getting loaded properly? I'm really not sure here. I'm going to post each file here, and hope one or more of you may be able to shine some light on this problem for me.

#Main menu Program
import cPickle as p
import sys

def MainMenu():
    print 'Main System Menu:'
    print 'Please select an option from the following:'
    print '1. Create new account.'
    print '2. Delete accounts.'
    print '3. End Program.'
    Choice = raw_input('Enter Selection: ')
    if Choice == '1':
        my_file = 'UserAccess.py'
        execfile(my_file)
    elif Choice == '2':
        my_file = 'UserDeleteAccess.py'
        execfile(my_file)
    elif Choice == '3':
        print 'Exiting Program, Have a nice day!'
        sys.exit()
    else:
        print 'Invalid selection'
        MainMenu()

Variable = MainMenu()
#User Access
import cPickle as p
import sys

def EP(self, temp):
    if self.lower() == 'exit':
        print 'Returning to Main Menu.'
        my_file = 'SystemMenu.py'
        execfile(my_file)
    if self.lower() in temp:
        print 'That username already exists.'
        NewAccount()

def NewAccount():
    my_file = 'systemaccess.txt'
    file_handle = open(my_file, 'r')
    temp = p.load(file_handle)
    file_handle.close()
    print 'Welcome to the System Account Setup.'
    print 'Enter Exit to return to Main Menu at anytime.'
    Username = raw_input('Please enter the username you desire: ')
    EP(Username.lower(), temp)
    Password = raw_input('Enter your desired password: ')
    EP(Password.lower(), temp)
    temp[Username.lower()] = Password.lower()
    file_handle = open( my_file, 'w' )
    p.dump(temp, file_handle)
    file_handle.close()
    print 'New account created.'
    CreateAccount()
    
def CreateAccount():
    repeat = 'Y'
    while repeat == 'Y':
        repeat = raw_input('Would you like to create another account?(Y/N):').upper()
        if repeat == 'Y':
            NewAccount()
        elif repeat == 'N':
            print 'Thank you for using the System Account Setup. Returning to Main Menu'
            my_file = 'SystemMenu.py'
            execfile(my_file)
        else:
            CreateAccount()

Variable = NewAccount()
#Delete access
import cPickle as p
import sys

def LoadAdmin():
    my_file = 'adminaccess.txt'
    file_handle = open(my_file, 'r')
    Adminfile = p.load(file_handle)
    file_handle.close()
    DeleteAll(Adminfile, my_file)
    
def LoadAccounts():
    my_file = 'systemaccess.txt'
    file_handle = open(my_file, 'r')
    Accountlist = p.load(file_handle)
    file_handle.close()
    Menu(Accountlist, my_file)

def Menu(Accountlist, my_file):
    print ''
    print 'Welcome to the Account Deletion Menu.'
    print 'Please choose from the following options.'
    print '*********************'
    print '1. Delete single account.'
    print '2. Delete all accounts.(Requires Administrator Access)'
    print '3. Exit to Menu.'
    print '*********************'
    Choice = raw_input('Enter Selection:')
    if Choice == '1':
        DeleteSingle(Accountlist, my_file)
    elif Choice == '2':
        LoadAdmin()
    elif Choice == '3':
        ExitToMenu()
    else:
        print 'Invalid Choice Selection.'
        Menu(Accountlist, my_file)
    

def DeleteSingle(Accountlist, my_file):
    print 'Please enter the account you wish to delete,'
    AccountDel = raw_input('Enter exit to return to the Account Deletion Menu: ').lower()
    if AccountDel.lower() == 'exit':
        Menu(Accountlist, my_file)
    elif AccountDel in Accountlist:
        AccountPass = raw_input('Please enter the pasword for this acount: ').lower()
    elif AccountDel not in Accountlist:
        print 'That account does not exist.'
        print
        DeleteSingle(Accountlist, my_file)
    if AccountPass == Accountlist[AccountDel]:
        del Accountlist[AccountDel]
        file_handle = open(my_file, 'w')
        p.dump(Accountlist, file_handle)
        file_handle.close()
        print 'Account has been Deleted.'
        LoadAccounts()
    else:
        print 'Invalid Password'
        print
        DeleteSingle(Accountlist, my_file)
        
def DeleteAll(Adminfile, my_file):
    Access = raw_input('Please enter administrator access code: ').lower()
    if Access == Adminfile['administrator']:
        my_file = 'systemaccess.txt'
        file_handle = open(my_file, 'r')
        Accountlist = p.load(file_handle)
        file_handle.close()
        Accountlist.clear()
        file_handle = open(my_file, 'w')
        p.dump(Accountlist, file_handle)
        file_handle.close()
        print 'All Accounts have been deleted.'
        print
        LoadAccounts()
    else:
        print 'Administrator Password incorrect.'
        print
        DeleteAll(Adminfile, my_file)
    

def ExitToMenu():
    my_file = 'SystemMenu.py'
    execfile(my_file)

Variable = LoadAccounts()

I hope someone can lead me down the right path here. And I'm so sorry for having posted multiple times here today. I've been at this for the better part of the day, and I'm quite happy with the progress I've made. I'm having alot of fun learning this stuff!!

Thanks in advance folks, you're all just great in my book.

Recommended Answers

All 5 Replies

In this menu program, you're programming an automaton in fact. This automaton has nodes which represent states where your system can be, these states are "SystemMenu", "UserAccess", "UserDeleteAccess", "Exit". When you're in one of these states, a callback function is called to show a menu and then move to a new state (technically, this is called a transition). These functions are "MainMenu", "NewAccount", "Menu", "LoadAccounts", and a function should be added for the "Exit" state.

You should avoid using mutliples execfiles. The good way to access multiple python programs in an application is to use the import statement. You should also avoid calling recursively your callback functions, which obfuscates the program.

A better desing would be to have a cursor which remembers the state where your system is and calls the appropriate callback function. This function in turn can change the cursor state and return. A loop will be the engine for the automaton. Here is how you could write this

#  file SystemMenu.py
import UserAccess
import UserDeleteAccess

def MainMenu(cursor):
    ...
    if Choice == '1':
        cursor.state = "UserAccess"
    elif Choice == '2':
        cursor.state = "UserDeleteAccess"
    elif Choice == '3':
        cursor.state = "Exit"
    else:
        print ...
        cursor.state = "SystemMenu"

def ExitCallback(cursor):
    sys.exit(0)

class Cursor(object):

    callbacks = {
        "SystemMenu" : MainMenu,
        "UserAccess": UserAccess.NewAccount,
        "UserDeleteAccess": UserDeleteAccess.LoadAccounts,
        "Exit": ExitCallback,
    }
    def __init__(self):
        self.state = "SystemMenu"

    def mainloop(self):
        # the 'engine' loop
        while True:
            # call the function corresponding tu the cursor's state
            self.callbacks[self.state](self)

cursor = Cursor()
cursor.mainloop()

In the other files, your callback functions should take the cursor as an argument, so that they can set the cursor's state before they return

# file UserAccess.py
...
def NewAccout(cursor):
    ...

def CreateAccount(cursor):
    ...
    elif...:
        cursor.state = "SystemMenu"
    else:
        cursor.state = "CreateAccount" # hey we must add a state

With this design, the trick is: drop all the "execfiles" and also change the cursor's state instead of calling recursively the menus ! You can then add as many nodes as you want to the automaton.
A more robust design would be to use objects everywhere, but it's not yet necessary.

While this worked wonderfully to call my UserAccess, and UserDeleteAccess file from within SystemMenu, I'm having trouble returning to SystemMenu from the other imported modules.

It keeps telling me MainMenu is not defined. I've tried Importing SystemMenu into both UserAccess and UserDeleteAccess, but it then gives me the error:

File "C:\Python25\Python\SystemMenu.py", line 30, in Cursor
"UserAccess" : UserAccess.NewAccount,
AttributeError: 'module' object has no attribute 'NewAccount'

I really appreciate the help so far, and searching for something this specific in google has been fruitless so far.

import UserAccess
import UserDeleteAccess
import sys
import cPickle as p

def MainMenu(cursor):
    print 'Main System Menu:'
    print 'Please select an option from the following:'
    print '1. Create new account.'
    print '2. Delete accounts.'
    print '3. End Program.'
    Choice = raw_input('Enter Selection: ')
    if Choice == '1':
        cursor.state = "UserAccess"
    elif Choice == '2':
        cursor.state = "UserDeleteAccess"
    elif Choice == '3':
        cursor.state = "Exit"
    else:
        print 'Invalid selection'
        cursor.state = "SystemMenu"

def ExitCallback(cursor):
    sys.exit()

class Cursor(object):

    callbacks = {
        "SystemMenu" : MainMenu,
        "UserAccess" : UserAccess.NewAccount,
        "UserDeleteAccess" : UserDeleteAccess.LoadAccounts,
        "Exit" : ExitCallback,
    }
    def __init__(self):
        self.state = "SystemMenu"

    def mainloop(self):
        while True:
            self.callbacks[self.state](self)

cursor = Cursor()
cursor.mainloop()
#User Access
import cPickle as p
import sys
import SystemMenu
def EP(self, temp, cursor):
    if self.lower() == 'exit':
        print 'Returning to Main Menu.'
        cursor.state = "SystemMenu"
    if self.lower() in temp:
        print 'That username already exists.'
        NewAccount(cursor)

def NewAccount(cursor):
    my_file = 'systemaccess.txt'
    file_handle = open(my_file, 'r')
    temp = p.load(file_handle)
    file_handle.close()
    print 'Welcome to the System Account Setup.'
    print 'Enter Exit to return to Main Menu at anytime.'
    Username = raw_input('Please enter the username you desire: ')
    EP(Username.lower(), temp, cursor)
    Password = raw_input('Enter your desired password: ')
    EP(Password.lower(), temp, cursor)
    temp[Username.lower()] = Password.lower()
    file_handle = open( my_file, 'w' )
    p.dump(temp, file_handle)
    file_handle.close()
    print 'New account created.'
    CreateAccount(cursor)
    
def CreateAccount(cursor):
    repeat = 'Y'
    while repeat == 'Y':
        repeat = raw_input('Would you like to create another account?(Y/N):').upper()
        if repeat == 'Y':
            NewAccount(cursor)
        elif repeat == 'N':
            print 'Thank you for using the System Account Setup. Returning to Main Menu'
            cursor.state = "SystemMenu"
        else:
            CreateAccount(cursor)
#Delete access
import cPickle as p
import sys

def LoadAdmin(cursor):
    my_file = 'adminaccess.txt'
    file_handle = open(my_file, 'r')
    Adminfile = p.load(file_handle)
    file_handle.close()
    DeleteAll(Adminfile, my_file, cursor)
    
def LoadAccounts(cursor):
    my_file = 'systemaccess.txt'
    file_handle = open(my_file, 'r')
    Accountlist = p.load(file_handle)
    file_handle.close()
    Menu(Accountlist, my_file, cursor)

def Menu(Accountlist, my_file, cursor):
    print ''
    print 'Welcome to the Account Deletion Menu.'
    print 'Please choose from the following options.'
    print '*********************'
    print '1. Delete single account.'
    print '2. Delete all accounts.(Requires Administrator Access)'
    print '3. Exit to Menu.'
    print '*********************'
    Choice = raw_input('Enter Selection:')
    if Choice == '1':
        DeleteSingle(Accountlist, my_file, cursor)
    elif Choice == '2':
        LoadAdmin(cursor)
    elif Choice == '3':
        ExitToMenu(cursor)
    else:
        print 'Invalid Choice Selection.'
        Menu(Accountlist, my_file)
    

def DeleteSingle(Accountlist, my_file, cursor):
    print 'Please enter the account you wish to delete,'
    AccountDel = raw_input('Enter exit to return to the Account Deletion Menu: ').lower()
    if AccountDel.lower() == 'exit':
        Menu(Accountlist, my_file, cursor)
    elif AccountDel in Accountlist:
        AccountPass = raw_input('Please enter the pasword for this acount: ').lower()
    elif AccountDel not in Accountlist:
        print 'That account does not exist.'
        print
        DeleteSingle(Accountlist, my_file)
    if AccountPass == Accountlist[AccountDel]:
        del Accountlist[AccountDel]
        file_handle = open(my_file, 'w')
        p.dump(Accountlist, file_handle)
        file_handle.close()
        print 'Account has been Deleted.'
        LoadAccounts(cursor)
    else:
        print 'Invalid Password'
        print
        DeleteSingle(Accountlist, my_file, cursor)
        
def DeleteAll(Adminfile, my_file, cursor):
    Access = raw_input('Please enter administrator access code: ').lower()
    if Access == Adminfile['administrator']:
        my_file = 'systemaccess.txt'
        file_handle = open(my_file, 'r')
        Accountlist = p.load(file_handle)
        file_handle.close()
        Accountlist.clear()
        file_handle = open(my_file, 'w')
        p.dump(Accountlist, file_handle)
        file_handle.close()
        print 'All Accounts have been deleted.'
        print
        LoadAccounts(cursor)
    else:
        print 'Administrator Password incorrect.'
        print
        DeleteAll(Adminfile, my_file, cursor)
    

def ExitToMenu(cursor):
    cursor.state = MainMenu(cursor)

You must not import SystemMenu in the other files (if A import B, then B should not attempt to import A), so you can't directly call MainMenu from the other files. What you should do is replace calls to MainMenu by a change of state

def ExitToMenu(cursor):
    cursor.state = "SystemMenu"

Similarly, calls to LoadAccounts should be replaced by cursor.state = "UserDeleteAccess"

Absolutely Perfect! I thank you sir, your responses are both to the point and quite thorough. And I really appreciate the quickness in which you have responded. Seeing as I'm not in a school related program to teach me these things, I find my self very grateful for having folks like yourself who are willing to aid me when I need it. You have no idea how much I appreciate this.

Kudos to you sir. /bow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.