0

 Ok, this is not very clear at all. Allow me to rephrase.

Quick note: "Solved" while writing this question. Will accept answer with inputs regarding best practices.

Original quick note: This is probably a duplicate. I apparently couldn't phrase the question well enough to fit this situation. My apologies if it is.

First of all, to get you situated, here is my project's hierarchy as well as some relevant code:

Project/
├── main.py
└── lib
    ├── __init__.py
    ├── A.py
    ├── B.py
    └── C.py

main.py:

## Imports
from lib.A  import ClassA   as clA
from lib.B  import ClassB   as clB
from lib.C  import ClassC   as clC

#
# ... Some other code ...
#

a = clA()
b = clB()

a.add_ClB_Inst_Ref(b)
    

A.py:

## Imports
if __name__ == "__main__":
    from B  import ClassB   as clB
    from C  import ClassC   as clC

class ClassA:

    dict_Of_Weighted_ClB_Refs = {}
    #
    # ... Some other code (attributes, init, ...) ...
    #
    
    def add_ClB_Inst_Ref(self, ClB_Instance):
    
        if isinstance(ClB_Instance, clB):
            key = clB.ID

            if key in self.dict_Of_Weighted_ClB_Refs:
                self.dict_Of_Weighted_ClB_Refs[key] +=1
            else:
                self.dict_Of_Weighted_ClB_Refs[key] = 1

Issue:

The program crashes in the add_ClB_Inst_Ref method when checking that the method's parameter is an instance of the ClassB object with the following error:

NameError: name 'clB' is not defined

"Well", you might say, "of course it crashes, the A.py files has never heard of that fancy clB!". And, yes this may be the problem, but when I try to import it inside this file, replacing the imports section with this:

## Imports
from B  import ClassB   as clB
from C  import ClassC   as clC

I get the following error: ImportError: No module named 'B'

Question:

How can I fix this? Your input on best practices would be most welcomed.

Suspicions:

All this leads me to these hypothesis:

  • Modules imported in a file at the root of the project aren't globally available for the duration of the program's execution.
  • import searches a match from where the initial script has been executed. (Note: This lead me to double check that I had tried it this way from lib.B import ClassB as clB just like in the main file; turns out I hadn't and this works... I get the logic, but it seems rather counter intuitive. See answer below for details.)
  • My project's architecture is flawed.
Community
  • 1
  • 1
Gormador
  • 380
  • 2
  • 15
  • Possible duplicate. http://stackoverflow.com/questions/4142151/python-how-to-import-the-class-within-the-same-directory-or-sub-directory – Januson Aug 19 '16 at 11:01
  • @Januson I don't think this qualifies as a duplicate. The question asked there concerns imports in _Folder/file.py_ of modules contained in _Folder/Subfolder/_, whereas my question is about this **combined** with using those same imported modules within files contained in _Folder/Subfolder/_ when executing the program from _Folder/file.py_ ... Yes, you can probably see why I struggled with my search for duplicates ;-) – Gormador Aug 19 '16 at 12:37

1 Answers1

0

As noted in the question, here is what is needed to fix the issue of the unavailable module B in module A.

Simply replace the imports section in A.py with the following:

## Imports
if __name__ == "__main__":
    from B  import ClassB   as clB
    from C  import ClassC   as clC
else:
    from lib.B  import ClassB   as clB
    from lib.C  import ClassC   as clC

This doesn't seem like the best possible solution to me, as this means that each time the module is called from somewhere else than the lib folder, it assumes this "somewhere" is the project's root folder, which could lead to some serious conflicts.

Please write you own answer if you are able to provide a more general approach and/or best practices on this issue.

Community
  • 1
  • 1
Gormador
  • 380
  • 2
  • 15
  • 1
    My understanding of best practices is that you should not use a module inside a package as an executable script at all. If you want to use a module to launch something, use Python's option to run a module (`python -m lib.A`). Then only use the package style imports. You can also do them as relative imports (i.e. `from .B import ...`). – Thomas K Aug 20 '16 at 22:39