How do I run a Bash script that calls a Python script from anywhere?

I have a Python script, say myscript.py

that uses relative module imports, i.e. from .. import module1

where my project layout looks like this:

project
 + outer_module
   - __init__.py
   - module1.py
   + inner_module
     - __init__.py
     - myscript.py
     - myscript.sh

      

And I have a Bash script, say myscript.sh

, which is a wrapper for my python script as shown below:

#!/bin/bash
python -m outer_module.inner_module.myscript $@

      

This works for execution myscript.py

and redirects arguments to my script as desired, but only works when called ./outer_module/inner_module/myscript.sh

from the directory project

shown above.

How can I make this script work from anywhere? For example, how can I make this work for a type call bash /root/to/my/project/outer_module/inner_module/myscript.sh

?

Here are my attempts:

When you run myscript.sh

from another location, I get the following error: No module named outer_module.inner_module

. Then I tried a different approach to execute a Bash script from anywhere, replacing myscript.sh

with:

#!/bin/bash
scriptdir=`dirname "$BASH_SOURCE"`
python $scriptdir/myscript.py $@

      

When I execute myscript.sh

as shown above, I get this:

Traceback (most recent call last):
  File "./inner_module/myscript.py", line 10, in <module>
    from .. import module1
ValueError: Attempted relative import in non-package

      

This is due to the relative imports on the first line in myscript.py

, as mentioned earlier, which is from .. import module1

.

+3


source to share


2 answers


You need to specify the path to the external module's parent directory in an environment variable PYTHONPATH

, then you can use the same command you used in the first script from anywhere.

PYTHONPATH

where python looks for any modules you are trying to import:



#!/bin/bash
export PYTHONPATH=$PYTHONPATH:PATH/TO/MODULE/PARENTDIR
python -m outer_module.inner_module.myscript $@

      

+2


source


As the error message says:

ValueError: Attempted relative import in non-package

      

The solution to this is to create a package and execute a script with that package in its path.



You already have a package because you have files __init__.py

in those directories; but you only have this package in your path when you call it from the project directory as you mentioned; because it .

is in your Python path by default.

To fix this, just add the project directory to your Python path and then call it with python -m outer_module.inner_module.myscript

:

#!/bin/bash
export PYTHONPATH=$PYTHONPATH:$(dirname "$BASH_SOURCE")/../..
python -m outer_module.inner_module.myscript $@

      

+2


source







All Articles