Sibling package imports
package, python, python-import, siblings
Solution
Seven years after
Since I wrote the answer below, modifying `sys.path` is still a quick-and-dirty trick that works well for private scripts, but there has been several improvements
- Installing the package (in a virtualenv or not) will give you what you want, though I would suggest using pip to do it rather than using setuptools directly (and using `setup.cfg` to store the metadata)
- Using the `-m` flag and running as a package works too (but will turn out a bit awkward if you want to convert your working directory into an installable package).
- For the tests, specifically, pytest is able to find the api package in this situation and takes care of the `sys.path` hacks for you
So it really depends on what you want to do. In your case, though, since it seems that your goal is to make a proper package at some point, installing through `pip -e` is probably your best bet, even if it is not perfect yet.
Old answer
As already stated elsewhere, the awful truth is that you have to do ugly hacks to allow imports from siblings modules or parents package from a `__main__` module. The issue is detailed in PEP 366. PEP 3122 attempted to handle imports in a more rational way but Guido has rejected it one the account of
The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern.
(here)
Though, I use this pattern on a regular basis with
# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
from sys import path
from os.path import dirname as dir
path.append(dir(path[0]))
__package__ = "examples"
import api
Here `path[0]` is your running script's parent folder and `dir(path[0])` your top level folder.
I have still not been able to use relative imports with this, though, but it does allow absolute imports from the top level (in your example `api`'s parent folder).
Problem
I've tried reading through questions about sibling imports and even the package documentation, but I've yet to find an answer. With the following structure: ``` ├── LICENSE.md ├── README.md ├── api │ ├── __init__.py │ ├── api.py │ └── api_key.py ├── examples │ ├── __init__.py │ ├── example_one.py │ └── example_two.py └── tests │ ├── __init__.py │ └── test_one.py ``` How can the scripts in the `examples` and `tests` directories import from the `api` module and be run from the commandline? Also, I'd like to avoid the ugly `sys.path.insert` hack for every file. Surely this can be done in Python, right?