0

I try to make my code more modular for general readability. When moving functions and dictionaries storing function names to external py.files in the same folder, it raises a name error. It does however work fine when in one file and the dict-file importing the function file (please see below):

Does not work:

data.py
modes = {'add' : {'adds an entry': addMode}} 

func.py
def addMode():
    print('tada')

Main file

from data import modes
from func import addMode
for v, button in modes.items():
    for tip, function in button.items():
        function()

Does work but seems messy:

data2.py
from func import addMode
modes = {'add' : {'adds an entry': addMode}}

Main file

from data2 import modes
for v, button in modes.items():
    for tip, function in button.items():
        function()

Is there a reason why the former does not work? It seems that order is of importance for the addMode in the dict to not cause a NameError, is there a way to force it?

Necrorubi
  • 80
  • 6
  • you want to use `func`'s `addMode` function, import it in `data.py`, not in `main.py`, would also work. – chickity china chinese chicken Apr 04 '17 at 21:18
  • I did in the latter example. Does work, but seems messy :( – Necrorubi Apr 04 '17 at 21:22
  • not sure what makes it seem messy, maybe because you prefer to see all imports in one location? maybe the functionality of `__all__` in an `__init__.py` file may be the way you'd want to organize your imports. [Loading all modules in a folder in Python](http://stackoverflow.com/questions/1057431/loading-all-modules-in-a-folder-in-python), or [modules tutorial](https://docs.python.org/3/tutorial/modules.html) – chickity china chinese chicken Apr 04 '17 at 21:29

1 Answers1

0

It doesn't have much to do with the order things are in — this is how namespaces work. data.py and func.py have different namespaces, and if you want to use something in one namespace from another, you need to import it. And importing something into the main file's namespace doesn't cause it to appear in data.py's namespace.

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • So, even though both are imported in the main function, they have separate namespaces? I thought (apparently foolishly) that the import function takes the thing to be imported and treats it as part of the script. – Necrorubi Apr 04 '17 at 21:20
  • So the "messy" way described above is indeed how it should work? – Necrorubi Apr 04 '17 at 22:13
  • @Necrorubi: `import` pulls in values from another namespace. You can think of a namespace as kind of like a dictionary. So your data.py file is kind of like `data_py = {}; data_py['modes'] = {'add' : {'adds an entry': data_py['addMode']}}`. Then when you do `from func import addMode` in data.py, that's like writing `data_py['addMode'] = func_py['addMode']`. Any symbol you reference has to have been brought into the current namespace somehow. – Chuck Apr 04 '17 at 22:17
  • @Necrorubi: So yes, the "messy" way is the Pythonic way to do it. There are other ways you could get around it, but they'd be more complicated and most are less Pythonic. – Chuck Apr 04 '17 at 22:19
  • Ah, great thanks for the advice and feedback. I am still rather new to python and have yet to get a grasp of what is pythonic vs hackish/depreciated. As I am new to SO, I cannot upvote yet. Is there anythin I can/should do to improve my etiquette (other than including MCV-Code)? – Necrorubi Apr 05 '17 at 06:51
  • I am sorry, but I have to ask: Is it necessary/possible to import names circularly? main.py contains tkinter widgets/frames, functions.py contains functions modifying/adding labels in main.py (importing stuff from data.py). The function works fine when embedded in main.py, but the point of the exercise was to keep functions, gui and data apart for easier maintenance. – Necrorubi Apr 05 '17 at 21:44
  • @Necrorubi: Circular imports aren't impossible but have a lot of limitations. It's generally best to avoid them. It seems to me that the supporting modules probably don't need to import your main.py. You can probably structure your code so that main.py imports the other modules and passes them any values they need to know about, and maybe put the widgets in their own modules, or something like that. (Obviously hard to say concretely from here.) – Chuck Apr 06 '17 at 21:37