Given
Let's say I have a code repository "my_tools" with some common code and some scripts (here e.g. fooscript) residing in subdirectories.
utils.py
def my_util():
print("baz")
fooscript.py
import sys; print(sys.path)
from commons.utils import my_util
my_util()
(all __init__.py
are empty)
What happens when running it
When I run fooscript from the my_tools root directory, here is what happens:
> python foo/fooscript.py
['/home/michel/my_tools/foo', ... python internals ... ]
Traceback (most recent call last):
File "foo/fooscript.py", line 3, in <module>
from commons.utils import my_util
ModuleNotFoundError: No module named 'commons'
This surprised me - I was expecting that running python interpreter from my_tools directory it would put my_tools onto sys.path. Instead it puts the parent directory of the script actually being run. Putting an __init__.py
in the root directory makes no difference.
Question
What are best practices to resolve this import issue? Approaches I have considered:
Adding my_tools manually onto PYTHONPATH variable, e.g. in a Makefile target.
Messing with sys.path inside the code. This is strictly worse than the above solution IMO.
Wrapping the scripts to be run under a common
my_tools.py
under the root directory. I guess OK, but it would be something that lives in addition to what is going to be run in AWS Lambda (each lambda only needing the commons directory plus the invidual script directory).Doing only relative imports instead. Not really an option here because for deployment I want to package commons on a separate AWS lambda layer, requiring absolute imports. Although it could be achieved using a custom docker image for lambda, but I'd still prefer to be able to steer the working directory.
Am I missing something here? If not wanting to add additional path or import manipulations, is the best practice here really to modify PYTHONPATH?
Background
the subtleties of this question come from the desire to run locally an AWS Lambda based repository of microservices with some common code put on a lower layer.