71

First off all: I'm sorry, I know there has been lots of question about relative imports, but I just didn't find a solution. If possible I would like to use the following directory layout:

myClass/
    __init__.py
    test/
        demo.py
        benchmark.py
        specs.py
    src/
        __init__.py
        myClass.py

Now my questions are:

  • How do the test files from within the package properly import myClass.py?

  • How would you import the package from outside, assuming you take myClass as submodule in libs/myClass or include/myClass?

So far I couldn't find an elegant solution for this. From what I understand Guido's Decision it should be possible to do from ..src import myClass but this will error:

ValueError: Attempted relative import in non-package

Which looks as it doesn't treat myClass as packages. Reading the docs:

The __init__.py files are required to make Python treat the directories as containing packages;

It seems I'm missing something that specifies where the scripts of the package are, should I use .pth ?

Ahmad
  • 69,608
  • 17
  • 111
  • 137
drivenuts
  • 1,039
  • 1
  • 7
  • 18
  • 6
    @Brent Newey, yes you are right, relative imports seems to be an ongoing topic and after reading quite a few answers I still felt the urge to specifically describe my situation. After showing this q, on the #python IRC channel quite a few people recommended to use flat directory structure: "A lot of people resist the way Python wants to use directories and files for semantic namespace information. It's best just to give in and do what Python wants." http://jcalderone.livejournal.com/39794.html – drivenuts Dec 03 '10 at 18:24
  • 8
    Could anyone provide a link to some real-world packages, with exemplary directory layout, or following some conventions? (ideally on github) – drivenuts Dec 03 '10 at 18:31
  • 1
    Is there `__init__.py` in the `test` directory? `ValueError: Attempted relative import in non-package` might be related to it. – jfs Dec 03 '10 at 20:48
  • http://stackoverflow.com/questions/1803292/initialize-project-layout-in-python http://docs.python.org/distutils/examples.html – jfs Dec 03 '10 at 20:53
  • Reading the official documentation helped me a lot! https://docs.python.org/3/reference/import.html#package-relative-imports – Kavin Raju S May 14 '20 at 01:20

3 Answers3

42

ValueError: Attempted relative import in non-package

Means you attempt to use relative import in the module which is not package. Its problem with the file which has this from ... import statement, and not the file which you are trying to import.

So if you are doing relative imports in your tests, for example, you should make your tests to be part of your package. This means

  1. Adding __init__.py to test/
  2. Running them from some outside script, like nosetests

If you run something as python myClass/test/demo.py, relative imports will not work too since you are running demo module not as package. Relative imports require that the module which uses them is being imported itself either as package module, from myClass.test.demo import blabla, or with relative import.

Daniel Kluev
  • 11,025
  • 2
  • 36
  • 36
28

After hours of searching last night I found the answer to relative imports in python!! Or an easy solution at the very least. The best way to fix this is to have the modules called from another module. So say you want demo.py to import myClass.py. In the myClass folder at the root of the sub-packages they need to have a file that calls the other two. From what I gather the working directory is always considered __main__ so if you test the import from demo.py with the demo.py script, you will receive that error. To illustrate:

Folder hierarchy:

myClass/
    main.py #arbitrary name, can be anything
    test/
        __init__.py
        demo.py
    src/
        __init__.py
        myClass.py

myClass.py:

def randomMaths(x):
    a = x * 2
    y = x * a
    return y

demo.py:

from ..src import myClass

def printer():
    print(myClass.randomMaths(42))

main.py:

import test.demo

demo.printer()

If you run demo.py in the interpreter, you will generate an error, but running main.py will not. It's a little convoluted, but it works :D

Nathaniel Jones
  • 939
  • 1
  • 14
  • 25
Sevvy325
  • 547
  • 2
  • 7
  • 16
  • 3
    I'm using Python 2.7 and I only got the above code to work by doing three things. First, at the level where main.py is, I added a `__init__.py`. Second, I changed demo.printer() to `test.demo.printer()`. Third, I changed directory above the main.py and ran `python -m myClass.main`. Otherwise, this was a very helpful answer to me. :) – Paul Jan 06 '14 at 23:19
0

Intra-package-references describes how to myClass from test/*. To import the package from outside, you should add its path to PYTHONPATH environment variable before running the importer application, or to sys.path list in the code before importing it.

Why from ..src import myClass fails: probably, src is not a python package, you cannot import from there. You should add it to python path as described above.

khachik
  • 28,112
  • 9
  • 59
  • 94
  • Relative imports are done all the time. Many packages have smaller sub packages with in them and rely on relative imports. the OP is not asking how to reference external packages. He is asking how to reference another sub package within a package. – cstrutton Nov 17 '15 at 19:02