我有一个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
并根据需要将参数转发给我的脚本,但只有在上面显示的project
目录中调用./outer_module/inner_module/myscript.sh
时才起作用。
我怎样才能使这个脚本从任何地方工作? 例如,我怎样才能使这个工作像bash /root/to/my/project/outer_module/inner_module/myscript.sh
?
这是我的尝试:
当从其他地方执行myscript.sh
,我得到错误: No module named outer_module.inner_module
。 然后,我尝试了另一种方法来从任何地方执行bash脚本,将myscript.sh
replace为:
#!/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
。
您需要将外部模块的父目录的路径包含在PYTHONPATH
环境变量中,然后您可以在任意位置使用第一个脚本中使用的命令。
PYTHONPATH
是python搜索你试图导入的任何模块的地方:
#!/bin/bash export PYTHONPATH=$PYTHONPATH:PATH/TO/MODULE/PARENTDIR python -m outer_module.inner_module.myscript $@
正如错误信息所示:
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 $@