Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Python imports in deployed/local packages

How can I write import foo.bar in __init__.py so it will load the system-wide version of foo/bar.py when run from most places, but will load the local version of bar.py when run from within foo‘s source directory?

# foo/__init__.py

from foo.bar import baz
baz()
# foo/bar.py
def baz:
    print('Hello")

This will always load the site-wide version of foo/bar.py, and never the local version.

From examples of other packages I have installed on-site, imports should be done with import foo.bar. (examples numba, pandas, scipy), but I’m not sure how they manage to develop these libraries (perhaps they always use virtual environments).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I also tried:

# foo/__init__.py
try:
    from bar import baz
except ModuleNotFoundError:
    from foo.bar import baz
baz()

This does work, but it is pretty verbose to repeat everywhere in the library, and it seems prone to name-clashes.

>Solution :

but I’m not sure how they manage to develop these libraries (perhaps they always use virtual environments)

Yes, I think 99% or so of python dev work uses virtualenvs. They’re really not too hard—you might want to have a look at something like poetry to manage them. There’s also the pep582 approach, but that hasn’t yet made it. However you can spin up a venv really easily these days:

cd path/to/project
python3 -m venv .venv
source .venv/bin/activate
# and then something like
pip install -e . # installs in editable mode

If you don’t want to do this, you can still have an __init__ which loads the right files, by using relative paths:

# foo/__init__.py
from .bar import baz

…at the cost of not being able to evaluate the __init__ in an editor. But you can still run it locally without installing! Just use:

python -m foo

from the dir above foo. Likewise you can use

python -m foo.bar

To load and execute foo/bar.py (assuming it does anything).

Note that if you take the usual approach of installing your package in editable mode inside a virtualenv and then working there, there’s no reason not to use the foo.bar approach—and you can evaluate stuff without worrying about what . means. Lots of people don’t like relative paths for exactly that reason.

If you do need to evaluate bits of foo/__init__.py, first do the imports manually in your repl and then send only the lines you care about.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading