我有一个Python脚本,比如myscript.py
,它使用相对模块导入,即from .. import module1
,我的项目布局如下:
project
+ outer_module
- __init__.py
- module1.py
+ inner_module
- __init__.py
- myscript.py
- myscript.sh
我有一个Bash脚本,比如myscript.sh
,它是我的python脚本的包装器,如下所示:
#!/bin/bash
python -m outer_module.inner_module.myscript $@
这可以执行myscript.py
并根据需要将参数转发到我的脚本,但它仅在我从上面显示的./outer_module/inner_module/myscript.sh
目录中调用project
时才有效。
如何让这个脚本可以在任何地方运行?例如,如何才能使此功能适用于bash /root/to/my/project/outer_module/inner_module/myscript.sh
之类的调用?
以下是我的尝试:
从其他任何地方执行myscript.sh
时,我收到错误:No module named outer_module.inner_module
。然后我尝试了另一种方法,从任何地方执行bash脚本,将myscript.sh
替换为:
#!/bin/bash
scriptdir=`dirname "$BASH_SOURCE"`
python $scriptdir/myscript.py $@
当我执行myscript.sh
如上所示时,我得到以下内容:
Traceback (most recent call last):
File "./inner_module/myscript.py", line 10, in <module>
from .. import module1
ValueError: Attempted relative import in non-package
这是由于myscript.py
中第一行的相对导入,如前所述,from .. import module1
。
答案 0 :(得分:2)
您需要在PYTHONPATH
环境变量中包含外部模块的父目录的路径,然后您可以在任何地方使用您在第一个脚本中使用的相同命令。
PYTHONPATH
是python搜索您尝试导入的任何模块的地方:
#!/bin/bash
export PYTHONPATH=$PYTHONPATH:PATH/TO/MODULE/PARENTDIR
python -m outer_module.inner_module.myscript $@
答案 1 :(得分:2)
正如错误消息所示:
ValueError: Attempted relative import in non-package
解决方法是创建一个包,让脚本在其路径中使用该包执行。
您已经有了一个软件包,因为这些目录中有__init__.py
个文件;但是,正如您所提到的,当您从项目目录中调用它时,您只在路径中包含该包;那是因为默认情况下.
在你的Python路径中。
要解决此问题,只需将项目目录添加到Python路径,然后使用python -m outer_module.inner_module.myscript
调用它:
#!/bin/bash
export PYTHONPATH=$PYTHONPATH:$(dirname "$BASH_SOURCE")/../..
python -m outer_module.inner_module.myscript $@