Python imports in deployed/local packages


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

# foo/

from import baz
# foo/
def baz:

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

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

I also tried:

# foo/
    from bar import baz
except ModuleNotFoundError:
    from import 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/
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

To load and execute foo/ (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 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/, first do the imports manually in your repl and then send only the lines you care about.

Leave a Reply Cancel reply