2

I have 3 python files: login, teacher_ui, and student_ui. All three of these use tkinter. The login file takes a name as an input and if the name is a valid table in a database, the login file imports the student_ui file to run it.

The problem I am having is that the student_ui file needs a variable called name, which is the input in login. I am struggling to import the variable into student_uias it changes all the time.

My code in login to load the student_ui file is:

elif name_data in names_list:
    opening_window.destroy()
    import student_ui

This then runs student_ui, which provides a different interface. The code for name_data is: name_data = name.get().lower()

The line of code in student_ui that needs name_data is: user_table_name = name_data. This line is throwing a NameError because name is not defined.

Therefore, how would I make student_ui take the name_data from login when login loads student_ui?

Some of the code for the student_ui is:

number_words = {
                        "Forty Five" : 45,
                        ...
                        "Nine Thousand, Eight Hundred and Sixty Four" : 9864
}

user_table_name = name_data

query = 'SELECT _45 FROM {} ORDER BY runid DESC LIMIT 
3'.format(user_table_name)
c.execute(query)
status_1 = c.fetchall()
if ('true',) in status_1:
    status_1 = True
else:
    status_1 = False

There is also code for label, inputs, marking, and large amounts of database writing and reading.

13smith_oliver
  • 414
  • 6
  • 13
  • 1
    How is your program structured, what runs the different files? – Isdj Jun 04 '17 at 15:42
  • The `login` file runs the different files in the format:`if condition: import student_ui` `elif other condition: import teacher_ui`. – 13smith_oliver Jun 04 '17 at 15:45
  • And are the UI's built with classes etc or just code? – Isdj Jun 04 '17 at 15:50
  • Just code, I didn't use classes as it seemed pointless. – 13smith_oliver Jun 04 '17 at 15:51
  • You can't pass arguments directly to a module being imported, period. One workaround I have used is shown in [this ActiveState recipe](http://code.activestate.com/recipes/65207-constants-in-python/) which replaces the module with an instance of a class. Note there is one [minor caveat](https://stackoverflow.com/questions/5365562/why-is-the-value-of-name-changing-after-assignment-to-sys-modules-name), but it's easily worked around. There are other techniques to pass data to the module indirectly (such through a file). – martineau Jun 04 '17 at 15:52
  • 1
    I would create a class and import that class from the module. In the constructor it would receive the name variable – Isdj Jun 04 '17 at 15:57
  • Would that class be all the code in `student_ui` as there is lots of code not in functions. – 13smith_oliver Jun 04 '17 at 16:06
  • 1
    Re: @IsaacDj suggestion: That would depend on what the code does. Some of it might have to be moved into methods of the class—like its `__init__()` method or new ones you'll need to create (and call somewhere). – martineau Jun 04 '17 at 16:16
  • @martineau yes indeed. it's basically a matter of comfort to the coder – Isdj Jun 04 '17 at 16:19
  • 13smith_oliver: If you want more concrete and formal answers, you'll need to [edit] your question and include the code for the `student_ui` module. If it's too long or complex, you'll need to create an MCVE (see [_How to create a Minimal, Complete, and Verifiable example_](https://stackoverflow.com/help/mcve)) and put it in instead. – martineau Jun 04 '17 at 16:24

1 Answers1

1

Per IsaacDj's comment: I would use classes.

First, I would encapsulate all of student_ui.py's code into classes to prevent unexpected code execution:

# student_ui.py

class StudentUI:
    def __init__(self, name):
        self.name = name

    def do_things(self):
        number_words = {
            "Forty Five" : 45,
            ...
            "Nine Thousand, Eight Hundred and Sixty Four" : 9864
        }

        query = 'SELECT _45 FROM {} ORDER BY runid DESC LIMIT 3'.format(self.name)

        c.execute(query)
        status_1 = c.fetchall()

        if ('true',) in status_1:
            status_1 = True
        else:
            status_1 = False

Then to make things easier, you could straight-up import student-ui - no having to conditionally import the module:

# login.py

from student_ui import StudentUI

def do_stuff(name_data):
    if name_data in names_list:
        opening_window.destroy()
        student_ui = StudentUI(name_data)
        student_ui.do_stuff()

if __name__ == "__main__":
    do_stuff()

You could also use if __name__ == "__main__": to prevent student_ui from executing on import.

alex
  • 6,818
  • 9
  • 52
  • 103