30

Hey all -- I am pulling my hair out with relative imports in Python. I've read the documentation 30 times and numerous posts here on SO and other forums -- still doesn't seem to work.

My directory structure currently looks like this

src/
    __init__.py
    main.py
    components/
        __init__.py
        expander.py
        language_id.py
    utilities/
        __init__.py
        functions.py

I want expander.py and language_id.py to have access to the functions module. I run python main.py which accesses the modules just fine with from components.expander import * and components.language_id import *.

However, the code inside expander and language_id to access the functions module:

from ..utilities.functions import *

I receive this error:

ValueError: Attempted relative import beyond toplevel package

I have gone over it a bunch of times and it seems to follow the documentation. Anyone have any ideas of what's going wrong here?

Machavity
  • 30,841
  • 27
  • 92
  • 100
apexdodge
  • 6,657
  • 4
  • 26
  • 33
  • 9
    You've already found the solution, but to explain why it's needed: the package should be entirely self contained. It won't treat src/ as a package when you're running main.py inside it. – Thomas K Nov 14 '10 at 01:29

1 Answers1

22

Nevermind, I solved it:

src/
    main.py
    mod/
        __init__.py
        components/
            __init__.py
            expander.py
            language_id.py
        utilities/
            __init__.py
            functions.py

main.py then refers to the subpackages as:

from mod.components.expander import *
from mod.utilities.functions import *

expander.py and language_id.py have access to functions.py with:

from ..utilities.functions import *

But the interesting thing is that I had a text file inside the components directory that expander.py uses. However, at runtime it couldn't locate the file even though it was in the same directory. I moved the text file to the same directory as main.py and it worked. Seems counter-intuitive.

apexdodge
  • 6,657
  • 4
  • 26
  • 33
  • 17
    All the new module importing stuff is broken and unintuitive. – Matt Joiner Nov 14 '10 at 01:20
  • 3
    Opening text files works from the working directory where you started the program, whereas importing is relative to the location of the script. You can use \_\_file\_\_ in a module to find its path, and hence refer to things in the same directory, although it's not very elegant. If the text file is static data for the program, it might be easier to make it into a Python module, and import it. – Thomas K Nov 14 '10 at 01:23
  • 1
    You can use `pkgutil.get_data()` (http://docs.python.org/library/pkgutil#pkgutil.get_data) to retrieve files using the module namespace to locate them. For example, `raw_data = pkgutil.get_data('mod.components', 'data.txt')` will retrieve the raw binary data from the file. – ncoghlan Feb 23 '11 at 04:22
  • for those who still find this answer working, this worked for me: [`sys.path.append(path)`](http://stackoverflow.com/a/279338/986067) – Forethinker Jun 25 '13 at 15:06
  • The solution is removing the __init__file in the project root direcotory. Creating a new folder "mod" was not necessary, – Giulio De Marco Feb 14 '17 at 12:56