Stuff undefined importing functions from other file

I’m writing a little software for managing infos for where I work (nothing about IT, coding or stuff like that…).
As a total newbie doing by-my-self, I’m writing it in a single file, but something doesn’t work properly and my IDE doesn’t raise any error.
So, for sure it is a logical error, but being it hard to find, I’m trying to save different single files for those functions that write on a same .csv file. The problem is that when I try to import those function (using ’ from path/to/directory import [module] ’ and [name_module].[name_function() ]) in the main.py, running it seems to recognize them, but it can’t find - for instance - a tkinter’s frame that would be open when imported in the main.py, saying “variable not defined”, but they are defined in the main.py.
What I have to do to make it works properly?

Please share an example of the code that is not working for us to read.
I would otherwise have to guess at the problem.

Python doesn’t support from path/to/directory import module.

Whatever you are actually doing, it’s not that.

Yes, sorry. I mean that I import the function from the directory where is the file.py where is the function I need.
Anyway, what I do in the main.py is this:

Import the function in the main.py (here, I already imported all the modules that I need for the whole program, i.e, tkinter, csv, filedialog, etc…) and then:

def show_dates():
    Dates.show_dts()

The function ’ show_dts() ’ is saved in another file.py
The function is this:

def show_dts():
    root.title("Dates schedule")
    frm_dates= Frame(root)
    frm_dates.pack()

    name_date = StringVar()

    def save_date():
        a_name_date = name_date.get()
        with open('/path/to/file.csv', 'a') as scheduler:
            writer_scheduler = csv.writer(scheduler)
            writer_scheduler.writerow([a_name_date])
        scheduler.close()

    def close_showdates():
        frm_dates.destroy()


    btn_close = Button(frm_date, text="x", command=close_showdates)
    btn_close.pack()

    btn_add = Button(frm_date, text="Aggiungi")
    btn_add.pack(side=BOTTOM)


    row_dates = ttk.Treeview(frm_appunt, columns="Date")
    row_dates['show'] = 'headings'

    row_dates.column('#0')
    row_dates.heading('#0')

    row_dates.column('#1')
    row_dates.heading('#1', text="Date")

    row_dates.pack()

    with open('/path/to/file.csv', 'r') as scheduler:
        reader_scheduler= csv.reader(scheduler)
        for row in reader_scheduler:
            dates = row[1]
            row_dates.insert("", 0, values=(dates))

    entry_dts = Entry(frm_dates, textvariable=name_date, width=26, borderwidth=3)
    entry_dts.pack(side=BOTTOM, pady=7)


    if __name__ == '__main__':
        root.mainloop()

Then, when I run the program, this is the error:

Avvio: python3 /path/to/main.py
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "/path/to/main.py", line 525, in show_dates
    Dates.show_dates()
  File "/path/to/file.py", line 3, in show_dates
    frm_dates = Frame(root)
NameError: name 'Frame' is not defined
*** Uscito normalmente ***

What I have to do to make it work properly?

Anyone, please?

You need to name the imported module that Frame is defined in.
I am not a tk programmer but i assume its in a tk import.

As said above, all the modules I need are already imported in the main.py…

Why do you keep us guessing as to the imports?

You probably did:

>>> import tkinter as tk
>>> f = Frame(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Frame' is not defined

While you should be doing:

>>> f = tk.Frame(None)
>>> print(f)
.!frame

Am I guessing right?

No. I did not imported tkinter as tk…

Ah, I missed the difference in the modules where the import and use are.

Importing in main.py does not make the names available in file.py. Each module is its own namespace. Importing a name (like Frame) is only effective in the module where the import is.

Start by reading the description of the import statement.

Edit: Originally copied the wrong part of your message. Confusing, sorry about that.

So, how can I make it works? That document doesn’t explain nothing but how import statements work.
The goal of this topic is “how to solve” the code I posted…

The error is that Frame is not defined.

file.py doesn’t contain a definition of that class, or any imports. The interpreter therefore cannot find it.

So, you need to import the module that provides Frame in file.py. Note that @barry-scott already said this above.

But in this way, I would have all the modules repeated for each single function and, in theory, more ram waste…
it seems strange to me that is not the possibility to “say” to file.py “once you are imported in main.py, read modules from there”…
Is there another way to do that? For sure I have not enough knowledge yet about software engineering and I can’t figure out other solutions for now. The goal of this is to resolve some logical error that are hard to find, so I’m trying to find different ways to work on the code

Without seeing the application as a whole, it’s difficult to know what the problems are and suggest appropriate solutions. I suspect that if you’ve got the same kind of imports scattered across the application, then there isn’t much in the way of an architecture - a structure, really - to it. You might have GUI code mixed up with file handling code for example, lacking what we call separation of concerns.

These kinds of issues aren’t necessarily the easiest for a beginner to deal with when you’re just learning the mechanics of getting the computer to do what you want. I certainly remember my early programs being poorly designed!

Besides necessity, are you interested in how you would structure a system for real? You may be, but equally you may not be and that’s fine I think. The same goes for potential memory issues: are you having memory related problems with your code now? If not, it’s probably a thing that doesn’t need too much attention right now. I don’t know anything really about how the interpreter deals with imports, so I’ll leave that for someone else to comment on.

But in this way, I would have all the modules repeated for each single
function

Most of us put more than one function in a file.

and, in theory, more ram waste…

Importing the same module multiple times doesn’t waste memory. The
module is imported only once, and the import statemen resuses the
module; at that point it just makes that names you decide to import
available.

The imported modules are kept in a mapping called sys.modules. When
you go:

 from tkinter import Frame

what is similar to going:

 Frame = sys.module["tkinter"].Frame

to get a local variable named Frame referring to the Frame class
from tkinter. The import statement has a whole lot of machinery
behind it to make that efficent.

it seems strange to me that is not the possibility to “say” to file.py “once you are imported in main.py, read modules from there”…

It’s a feature. Generally you only want the names you’re going to use
cluttering up your file’s namespace. SO that namespace starts empty and
you import things and define variables and functions as required.

Is there another way to do that? For sure I have not enough knowledge
yet about software engineering and I can’t figure out other solutions
for now. The goal of this is to resolve some logical error that are
hard to find, so I’m trying to find different ways to work on the code

Generally you want to make the problematic code as small as possible,
and ideally have a way to run just the problematic code, not
“everything”. So you might write a “test” function to invoke just the
problem, and check various things. It is difficult to be more specific
without some example code to talk about.

Cheers,
Cameron Simpson cs@cskk.id.au

You’ve got a lot to learn here – I recommend that you keep it all in one file for now – once it gets too big, it does make sense to pu things in multiple files – but it will make it harder to debug, not easier :slight_smile: (or at least there’s a new set of bugs possible, as you’ve discovered)

It can be yes – my primary advise it to, as much as possible, keep you code in small functions, and make sure each function is working before you start using it in the larger program. And if a function isn’t working, go through it line by line, adding print() as you need to to make sure each line is doing what you expect …

The problem here descripted is that single functions are in separated files…

I already do it both in a different file and IDE. Basically, they works. The problem raises when I copy/paste the test code in the main.py. IDE doesn’t raise any error but functions don’t work properly as they would do. For that reason, I’m trying to put each single function in separated files to import in the main.py, but if it is necessary to import each module in each single file only for investigate a logical error like that, maybe is not so convenient I guess. But in this way, more problems related to the import statement raise, so I’m guessing that maybe do the things like this is not so convenient…

If you want to put code in separate files, you’re going to have to learn about how modules, namespaces, and import all work – which is good stuff to learn, but I think you’re mistaken in thinking it will make things easier to debug – it should not be hard to simply run / call one function while it’s still in the main script file. If nothing else, you can comment out everything you don’t want to test at the moment.

That’s because it’s a runtime error – Python is s dynamic language – there are a LOT of errors that won’t show up until runtime.

That being said – if you use a linter, such as pylint, or flake8, or … with your IDE (and if your IDE does not support that, find a new IDE) – it should give you a warning about undefined names.

Improve your Python code with Python linters | DS Stream.

(note: I don’t know if that’s a great article – it’s just the one that popped up first when I googled)

The problem here descripted is that single functions are in separated files…

Ok, but why?

I already do it both in a different file and IDE. Basically, they
works. The problem raises when I copy/paste the test code in the
main.py. IDE doesn’t raise any error but functions don’t work properly
as they would do. For that reason, I’m trying to put each single
function in separated files to import in the main.py, but if it is
necessary to import each module in each single file only for
investigate a logical error like that, maybe is not so convenient I
guess. But in this way, more problems related to the import statement
raise, so I’m guessing that maybe do the things like this is not so
convenient…

I’ve been thinking about a different way to describe this to you.

As I understand it you have a main.py with all your code in it. That
code has some bugs.

Do debug the problems you’re copying the function you want to debug into
another file which I assume also has some code to call the function to
test it. And you’re finding the imports etc tedious and I’m guessing the
function doesn’t work if it calls some of the other functions from
main.py.

I suggest leaving all your code in main.py.

For testing debugging, make your separate test file, and import the
functions from main:

 from main import func1

 ... call func1() as desired ...

In this way the functions are all defined in main.py where the imports
are, and where any functions they use are also defined.

In your separate test file you only need to import the name of the
function(s) you want to call. When that function itself runs, it is
operating in the namespace of the main.py file, so it already has
access to all the things from there it expects.

Cheers,
Cameron Simpson cs@cskk.id.au

You centered the point. I didn’t thought to import from the main.py to test it. I will try soon as possible.
Anyway, I would apologize with everyone on this forum for my silly questions but I’m trying to learn coding all by my self using only internet and some books. I have to do it between a day and another, when my job permit it.
I start to learn coding with python for audiophile purposes, but for needing, I started to learn it trying to develop a little stupid software for the little company where I work (in the healthcare system). I’m doing it as a voluteer and I have no other possibilities to learn both coding and python in another way. Where I live there aren’t chances to learn stuff like that. So, this is the point. At my side, I have great inventiveness anyway…
Thanks everyone and sorry for the Off Topic.