Understanding relative imports in package - and running pytest with relative imports?

Victor Hooi victorhooi at gmail.com
Mon Nov 25 02:30:27 CET 2013


Hi,

Ok, this is a topic that I've never really understood properly, so I'd like to find out what's the "proper" way of doing things.

Say I have a directory structure like this:

    furniture/
        __init__.py
        chair/
            __init__.py
            config.yaml
            build_chair.py
        common/
            __init__.py
            shared.py
        table/
            __init__.py
            config.yaml
            create_table.sql
            build_table.py

The package is called furniture, and we have modules chair, common and table underneath that.

build_chair.py and build_table.py are supposed to import from common/shared.py using relative imports. e.g.:

    from ..common.shared import supplies

However, if you then try to run the scripts build_chair.py, or build_table.py, they'll complain about:

    ValueError: Attempted relative import in non-package

After some Googling:

http://stackoverflow.com/questions/11536764/attempted-relative-import-in-non-package-even-with-init-py
http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python
http://stackoverflow.com/questions/18888198/getting-attempted-relative-import-in-non-package-error-in-spite-of-having-init
http://stackoverflow.com/questions/14664313/attempted-relative-import-in-non-package-although-packaes-with-init-py-in
http://melitamihaljevic.blogspot.com.au/2013/04/python-relative-imports-hard-way.html

The advice seems to be either to run it from the parent directory of furniture with:

    python -m furniture.chair.build_chair

Or to have a main.py outside of the package directory and run that, and have it import things.

However, I don't see having a separate single main.py outside my package would work with keeping my code tidy/organised, and or how it'd work with the other files (config.yaml, or create_table.sql) which are associated with each script?

A third way I thought of way just to create a setup.py and install the package into site-packages - and then everything will work? However, I don't think that solves my problem of understanding how things work, or getting my directory structure right.

Although apparently running a script inside a package is an anti-pattern? (https://mail.python.org/pipermail/python-3000/2007-April/006793.html)

How would you guys organise the code above?

Also, if I have tests (say with pyttest), inside furniture/table/tests/test_table.py, how would I run these as well? If I run py.test from there, I get the same:

    $ py.test
     ....
     from ..table.build_table import Table
     E   ValueError: Attempted relative import in non-package
    ....

(Above is just an extract).

Assuming I use pytest, where should my tests be in the directory structure, and how should I be running them?

Cheers,
Victor



More information about the Python-list mailing list