1

I have this project structure:

Scripts

-- A
    == AA
        ++ __init__.py
        ++ AAA.py
        ++ AAB.py
        ++ AAC.py
    == AB
        ++ __init__.py
        ++ ABA.py
        ++ ABB.py
        ++ ABC.py
-- B
    == BA
        ++ __init__.py
        ++ BAA.py
        ++ BAB.py
        ++ BAC.py
    == BB
        ++ __init__.py
        ++ BBA.py
        ++ BBB.py
        ++ BBC.py

I want to import classes inside Scripts/A/AA/AAA.py into Scripts/B/BB/BBC.py. I have used some solutions:

  1. from AAA import * gives me ImportError: No module named AAA.
  2. from Scripts.A.AA.AAA import * gives me ImportError: No module named Scripts.A.AA.AAA.
  3. from ..A.AA.AAA import * gives me ValueError: Attempted relative import beyond toplevel package.
  4. from ....A.AA.AAA import * gives me ValueError: Attempted relative import in non-package.

what should I do ?

EDIT 1:

I have changed the project's structure and now it's something like this:

Scripts

-- elements
    == A
        ++ __init__.py
        ++ AAA.py
        ++ AAB.py
        ++ AAC.py
    == B
        ++ __init__.py
        ++ BAA.py
        ++ BAB.py
        ++ BAC.py
-- general
    == imports.py
    == __init__.py
-- main.py

I have wrote this piece of code to import all classes:

elementDict = []
dirList = os.walk('elements') 
for dname in dirList:  
    fileList = dname[2]
    for fname in fileList:
        if fname != '__init__.py' and fname.endswith('.py') and (not fname.endswith('_ut.py')) and (not fname.endswith('~')):  
            path = dname[0].split(os.sep)
            path = filter(None, path[path.index('elements'):])
            dir = '.'.join(path)
            mod = importlib.import_module(dir + '.' + fname[:-3])
            for cname, obj in inspect.getmembers(mod, inspect.isclass): 
                if cname not in elementDict:  
                    elementDict[cname] = obj

This results in:

Traceback (most recent call last):
  File "C:\Users\test\Scripts\general\imports.py", line 29, in __init__
    mod = importlib.import_module(dir + '.' + fname[:-3])
  File "C:\Python27\lib\importlib\__init__.py", line 37, in import_module
    __import__(name)
ImportError: No module named elements.A.AAA

Any idea?

EDIT 2:

I have resolved the problem; I did not have any __init__.py in elements.

Community
  • 1
  • 1
Zeinab Abbasimazar
  • 9,835
  • 23
  • 82
  • 131

1 Answers1

1

Relative imports only work within a package structure. See this question for more detailed answers.

In this case AA and BB are two different packages, so the relative imports in 3 and 4 fail. Scripts isn't a package at all (neither are A or B), so 2 fails and since it's not likely, that you have Scripts/A/AA in your PYTHONPATH also 1 fails.

You need to have Scripts/A in your PYTHONPATH and then call from AA.AAA import *. If you already have Scripts in the PYTHONPATH, you could add a Scripts/A/__init__.py file to make the directory a python package and call from A.AA.AAA import * instead.

Community
  • 1
  • 1
tynn
  • 38,113
  • 8
  • 108
  • 143
  • I checked the `os.environ['PYTHONPATH']` and `Scripts` was there; but I got `No module named A.AA.AAA` for `from A.AA.AAA import *`. – Zeinab Abbasimazar Sep 13 '14 at 09:19
  • I just saw, that `A` isn't a package at all. How did you import the module `BB.BBC`? – tynn Sep 13 '14 at 09:56
  • I did not import it anywhere. – Zeinab Abbasimazar Sep 13 '14 at 10:55
  • I updated the answer to reflect the actual structure of your project. Since `Scripts` is in your PYTHONPATH the second approach (adding `Scripts/A/__init__.py`) might be best suited for your. – tynn Sep 13 '14 at 11:06
  • Is there any other way than that which does not affect project structure? – Zeinab Abbasimazar Sep 13 '14 at 11:32
  • Fiddling with the PYTHONPATH or any other import method with the [imp](https://docs.python.org/2/library/imp.html) or the [importlib](https://docs.python.org/3/library/importlib.html) module. You should update your question, explaining what you want to do or ask another one. – tynn Sep 13 '14 at 11:45