Skip to content Skip to sidebar Skip to footer

How Can I Create Imports That Always Work?

I am struggling a bit to set up a working structure in one of my projects. The problem is, that I have main package and a subpackage in a structure like this (I left out all unnece

Solution 1:

Unfortunately relative imports and direct running of submodules don't mix.

Add the parent directory of mypackage to your PYTHONPATH or always cd into the parent directory when you want to run a submodule.

Then you have two possibilities:

Use absolute (from mypackage import utils) instead of relative imports (from . import utils) and run them directly as before. The drawback with that solution is that you'll always need to write the fully qualified path, making it more work to rename mypackage later, among other things.

or

Run python3 -m mypackage.utils etc. to run your submodules instead of running python3 mypackage/utils.py.

This may take some time to adapt to, but it's the more correct way (a module in a package isn't the same as a standalone script) and you can continue to use relative imports.

There are more "magical" solutions involving __package__ and sys.path but they all require extra code at the top of every file with relative imports you want to run directly. I wouldn't recommend these.

Solution 2:

You should create a structure like this:

flammi88
├── flammi88
│   ├── __init__.py
│   ├── code.py
│   └── mypackage
│       ├── __init__.py
│       ├── utils.py
│       └── work.py
└── setup.py

then put at least this in the setup.py:

import setuptools
from distutils.core import setup

setup(
    name='flammi88',
    packages=['flammi88'],
)

now, from the directory containing setup.py, run

pip install -e .

This will make the flammi88 package available in development mode. Now you can say:

from flammi88.mypackageimport utils

everywhere. This is the normal way to develop packages in Python, and it solves all of your relative import problems. That being said, Guido frowns upon standalone scripts in sub-packages. With this structure I would move the tests inside flammi88/tests/... (and run them with e.g. py.test), but some people like to keep the tests next to the code.

Update:

an extended setup.py that describes external requirements and creates executables of the sub-packages you want to run can look like:

import setuptools
from distutils.core import setup

setup(
    name='flammi88',
    packages=['flammi88'],
    install_requires=[
        'markdown',
    ],
    entry_points={
        'console_scripts': [
            'work = flammi88.mypackage.work:someMethod',
        ]
    }
)

now, after pip installing your package, you can just type work at the command line.

Solution 3:

Import utils inside the work.py as follows:

import mypackage.utils

or if you want to use shorter name:

from mypackage import utils

EDIT: If you need to run work.py outside of the package, then try:

try:
    from mypackage import utils
except ImportError:
    import utils

Solution 4:

Use:

from . import utils

as suggested by Peter

In your code.py you should use:

from mypackage import work

Post a Comment for "How Can I Create Imports That Always Work?"