"Including" variables and constant decs from another file not working

I may be overthinking this, so could use some insight.

I have my Python code set up as follows:
(…couple of levels down from root (\))
|----->_System Software (dir)
|---------->FreqCntr_Sys.pyw
|---------------->FreqCntrFuncts (dir)
|---------------------->__pycache__ (dir)
|---------------------->__init__.py
|---------------------->FCSystemText.pyw
|---------------------->. (a number of other Python files)

(NOTE: I assume the __pycache__ dir with a number of .pyc files, is where the “compiled” code of my Python files is kept)

In my main program file (FreqCntr_Sys.pyw) before any class or def declarations I have

from FreqCntrFuncts.FCSystemText.pyw import *

FCSystemText.pyw contains text, variable and constant declarations (no methods or functions) as a means to keep all my declarations in one place (kind of the equivalent of “include” in an assembler file). I also have “global” statements in any methods or functions that need access to these global definitions.

Unfortunately, this doesn’t seem to be working. When my program tries to access a variable or constant that I believe should have been imported, I get a

NameError: name '<varname>' is not defined

I read on another forum ((stackflow?) that I could check for a valid import with the following code

from FreqCntrFuncts.FCSystemText import *
 if "FreqCntrFuncts.FCSystemText" not in dir():
         print("FCSystemText not imported!")

and the result I get is:

FCSystemText not imported!

However, if I place the explicit declaration in my main file (right after the other “import” statements), the error does not happen.

To clarify (and, hopefully, not make things more muddy :frowning: all I’m looking to do is import the file as text, if that makes sense or is possible with how Python operates. As I mentioned above, I’m thinking it might be like an “include <filename>” in assembler language. The include simply replaces the include statement with the text contents of the file. No preprocessing takes place (since an assembler operates more like a compiler). Can/does Python operate that way?

I expect I’m missing something fairly straightforward about this.

Help and insight appreciated, as usual :slight_smile:

Thx and cheers…

When you do:

from module import *

Then all the names in the module are imported directly into the current module, but without the module name prefix. In other words, when you import with the * and you want to access some item foo in that module, then you just say foo instead of module.foo.

Also, using ... import * is considered a bad practice in most situations because it muddies up the local namespace and it becomes more difficult to track down where something actually lives. It’s usually considered a better practice to import just the specific items you need from the module, like:

from module import foo, bar

Or, if you need to access more than just a few things in the module to just do import module and use the module name to access the items within it, like module.foo and etc.

This is where I’ve had the problem. I keep getting

NameError: name '<varname>' is not defined

I just tried this second method and now I get

NameError: name '<module name>' is not defined

It seems the file is not getting imported at all. Since that file is in the directory right “below” where my main program is located, it seems I may not be accessing it correctly. Pls see previous posting for sturcture and import command for this… Thx.

Are you sure you imported it? If you did and you did not get an ImportError then there should be a module with that name. To double-check you can print(moduleName) to see where it was imported from. And print(dir(moduleName)) will show you what is in the module that got imported.

If that doesn’t help them please share the relevant parts of your code again.

Robin,

I appreciate your continued patience and support :slight_smile:

Think I figured it out. I needed to structure the “import” statements as

from FreqCntrFuncts import <filename>

where <filename> is (obviously) the name of the file I want to import. What I was missing is that it seems FreqCntrFuncts is the package and

from FreqCntrFuncts.FCSystemText import *

wasn’t going to work with what I was trying to do (still not completely clear why). I have 3 other “modules” (basically definition files) in that same directory/package. I tried

from FreqCntrFuncts import *

but it wouldn’t let me generalize the import statement that way. I had to explicitly import each module/file.

Well, it does work now. Doing a print() and print(dir()) now shows a) the modules are indeed imported and, b) lists all the variables and constants I defined in those files. And that leads me to a somewhat related question…

In one of the import files I also have ~20 font definitions used throughout my app, i.e.:

btn_helv10bold = wx.Font(10, wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)

but none of those show up as valid declarations (I get “NameError: name ‘btn_helv10bold’ is not defined” in a method within the class). They’re not simple variable or constant declarations. But I thought they’re be recognized. I do have an “import wx” statement early in the code outside of my class statement. Is there something else or something different (like put them in a separate file and/or import them inside my class) I need to be doing to import these wx.Font statements? Or is that not possible?

My code structure for reference:

| |

Thx and cheers…

Are you importing btn_helv10bold in the module where you want to use it?

Not quite clear on your question…

If you look at my original post, I show the setup of my files. As the mapping shows, my main program is in the _System Software directory. In that same directory is a FreqCntrFuncts dir (which is now a package by adding the __init__.py file? Note: there is no __init__.py in my “top” directory. Do I need one there, as well?). In FreqCntrFuncts are a number of files, and in particular, FCSystemText.pyw. In this file are numerous variable and constant defs. I also recently added a method (unbounded?) that is designed to create the fonts I need for GUI in my main app. Here’s a sample of that file:

#
# Font and char definitions
#
#
def font_init():
	global btn_helv10bold, btnlbl_helv11boldital, btnlbl_helv11, optlbl_helv09bold, optlbl_helv09boldital, optlbl_helv09
	global btn_helv12bold, btn_helv12boldital, btn_helv24bold, btn_helv16bold, helv74bold
	global helv74boldital, helv40bold, helv50bold, helv50boldital, helv45bold
	#
	btn_helv10bold = wx.Font(10, wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
-----
...snipped a bunch of other font creations.....
-----
#
BULLET_CHAR = "\u25CF"
BULLET_HOLE = "\u25CB"
#
PWR_ON = False
CUR_MFUNC = 0x00
FEOPTS_MENU = 0x00
-----
....snipped a whole bunch of variable and constant definitions.....
-----

Since I assume Python wants to import the individual font def statements as objects/refs, I came across a solution that sounded like I could import the font creation as a method/function and then execute from with in my main program. Is that a Pythonic thing to do? And should I be able to do that?

Thanks…

From the NameError message it sounded like you were trying to use the obj without having imported it, assuming it actually existed in the imported module.

In Python every module has an independent namespace, usually called the module’s global namespace. (There are also nested namespaces for functions and methods, but they are not relevant at the moment.) When you import a module, or items from a module, then you are simply adding new names to the current module’s namespace that refer to the same objects in the namespace of the imported module. When you import moduleName then you are adding a new name to the current module’s namespace, “moduleName” that is a reference to the moduleName module. When you do from moduleName import foo then you are adding a new name to the current module, “foo” that is a reference to the same object that the “foo” name in the moduleName module’s namespace is referring too.

Since every module has an independent namespace then you have to import everything that the code needs to use from some other module (unless is is also defined in the current module). You can’t just import something once in one module and automatically have it available in other modules. From your prior message it sounds like you might have expected it to work that way. Instead, the other modules also need to import it if they need to use it too. If a particular module has already been imported somewhere, then subsequent imports don’t execute the module code agan, the subsequent imports just get a new reference to the currently loaded module object.

It would work, but I wouldn’t call it Pythonic.

First of all, there really isn’t any need to precreate fonts[*]. Creating therm as needed and then letting them be thrown out when done drawing or after creating a widget using them is fine. wxWidgets will take care of reference counting them and in some cases reusing them for you when it is necessary.

Secondly, creating a bunch of globals like that seems real messy. What happens when you want to change some font from 45 points to 46? You would have to change the name of the global and search/replace all uses of it and change them all.

Wanting to centralize the definition and creation of all the fonts is a good idea, but all the places they are used should not care what their face, size and style are. All they care about is getting the right font for what they are needing a font for. So I would go up a level of abstraction a give each of those font types a name, like “button-bold” or “label-headline” or whatever makes sense to you. Then I would make a dictionary that maps those names to a tuple of wx.Font parameters and a function that takes the name and returns a font.

_fontMap = {
    'button-bold': (10, wx.SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD),
    ...
}

def get_font(name):
    args = _fontMap[name]
    return wx.Font(*args)

Next, I would go up another level of abstraction and put all of that into a singleton class, with perhaps some more intelligence about the context and platform and be a little more dynamic about what parameters are actually used to create the font. But I’ll leave that as an exercise for the reader. :wink:

[*] Not to mention that the fonts can not be created before the wx.App object is created anyway.

Again, appreciate your time in helping me understanding this Python “stuff”. You’ve offered a lot for me to consider so I’ll have to go ponder it and try to grasp it in my own sense of things…and then play with it so I get the gist of it all. I am certainly much more a visual experimenter than a theoretician so I’ll go off and compose for a bit until I reach my next point of needing more insight and guidance.

Thanks and cheers…

I figured out my import issue which was giving me fits. And your suggestion about restructuring the font creation was a good idea. I still may play around with my original approach and see which one I like the best.

The biggest challenge I face is my background in assembler (cross assembling, to be precise). If you’ve ever worked at that level, nothing can be assumed about anything. Everything you want to do needs to be explicitly specified. As an example…related to scope…any routine that needs to access code in another module must tell the assembler/linker that is to happen (“public”). However, for those routines to be accessible then that, too, must also be specified (“extern”) or the connection will never be made. With Python, part of that function is implicit by where a variable, constant or function is defined, but not all of it.

And that points out my mindset…I’m used to having to be very explicit in my coding. So, as I’ve been moving to high level languages I find I overestimate the implicit things provided by the language and have to learn there are limitations. Terminology is also something I have to learn.

It’s a process, sometimes slow, but I’m getting there. So this is my roundabout way of saying “thanks” for your patience in helping me walk this path :slight_smile:

I did have 1 last question, tho. I moved my dictionary of fonts back to a separate file. Now I seem to need a

import wx

in both files. If I express that in only one or the other file I get a “NameError” for wx. Does that have to do with the scope and/or namespace aspect?

Cheers and thx…

OK. Got a few more questions :slight_smile:

This 1st one isn’t critical but more to ensure I’m understanding some of the terminology…

If you refer to my 1st posting above showing how I’ve structured my files

Is it correct to refer to “FreqCntrFuncts” as a package and the files (.py, .pyw, etc.) in that directory as modules (since I created an __init.py__)?

The important ???..

importing…

I placed my font dictionary in FCSystemText.pyw (which also has a number of variables and constants). When I did

from FreqCntrFuncts import FCSystemText

most variables and constants were imported (more on that in a moment), but not my font dictionary. I had to explicitly do

from FCSystemText import font_library

and that solved my NameError (but when I did a print(dir(FCSystemText)) the font dictionary was not listed). So, that means I have to do that for each method or non-variable/constant that I want to import (but should not do it using “*”). True?

Back to the importing of constants/variables for a moment…

While most of the variables and constants were imported, there were a few that were not. Nothing unique about them. What I realized was that I had repeated a couple of those definitions (need to do some cleanup) in another file/module in that “package” and those were actually imported (under that different namespace?). I just went back this morning and explicitly imported 2 of the variables that were not automatically imported

from FCSystemText import font_library, BULLET_CHAR, BULLET_HOLE

and that seemed to solve the NameError. Any insight on why that?

scope…

My understanding is that if I import a module (or the contents, thereof: methods, variables, constants, etc.) outside of a class, then those objects are implicitly “global”. That means any statement in a class or in a method/function defined in the class should be able to read the variable/constant without any global statements needed. The only time I would need to globalize something inside a class or method is if it’s a variable that will be both read and written by other method(s). Have I got that right?

OK. Good for now.

Thx and cheers…

Reading this page will probably help fill the knowledge gaps you still have about importing things.

I appreciate the link. I’ll check it out and see what I don’t know :slight_smile:

Thx and cheers…

I wanted to circle back around 1 last time on this specific topic (tho, I expect I may be back over time :wink: and say, again, how much I really appreciate the help!

I had a fairly good concept of modules and packages, but the articles helped fill in some of the gaps. The other thing I realized (after playing around with the importing function) is that, overall, I have to keep in mind that in some places (and importing was one of them) Python requires me to remember to be much more explicit in how I reference things, especially when I’m dealing with global variables. The import function taught me this very clearly after I better understood it.

So, I’m back on track coding (rather than figuring out where i messed up :frowning:
Again, thanks for the patience, help and insight.

Happy holidays and wishes for a great new year and beyond :slight_smile:

Cheers…Steph