简体   繁体   English

如何运行从任何位置调用Python脚本的Bash脚本?

[英]How to run a Bash script that calls a Python script from any location?

I have a Python script, say myscript.py , that uses relative module imports, ie from .. import module1 , where my project layout is as follows: 我有一个Python脚本,比如myscript.py ,它使用相对模块导入,即from .. import module1 ,我的项目布局如下:

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, shown below: 我有一个Bash脚本,比如myscript.sh ,它是我的python脚本的包装器,如下所示:

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

This works to execute myscript.py and forwards the arguments to my script as desired, but it only works when I call ./outer_module/inner_module/myscript.sh from within the project directory shown above. 这可以执行myscript.py并根据需要将参数转发到我的脚本,但只有在我从上面显示的project目录中调用./outer_module/inner_module/myscript.sh时它才有效。

How can I make this script work from anywhere? 如何让这个脚本在任何地方都可以工作? For example, how can I make this work for a call like bash /root/to/my/project/outer_module/inner_module/myscript.sh ? 例如,我如何使这个工作适用于像bash /root/to/my/project/outer_module/inner_module/myscript.sh这样的调用?

Here are my attempts: 以下是我的尝试:

When executing myscript.sh from anywhere else, I get the error: No module named outer_module.inner_module . 当从其他任何地方执行myscript.sh ,我得到错误: No module named outer_module.inner_module Then I tried another approach to execute the bash script from anywhere, by replacing myscript.sh with: 然后我尝试了另一种方法从任何地方执行bash脚本,方法是将myscript.sh替换为:

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

When I execute myscript.sh as shown above, I get the following: 当我执行如上所示的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

Which is due to the relative import on the first line in myscript.py , as mentioned earlier, which is from .. import module1 . 这是由于myscript.py第一行的相对导入,如前所述, from .. import module1

You need to include the path to the outer module's parent directory in the PYTHONPATH environmental variable, then you can use the same command you used in the first script from anywhere. 您需要在PYTHONPATH环境变量中包含外部模块的父目录的路径,然后您可以从任何地方使用您在第一个脚本中使用的相同命令。

The PYTHONPATH is where python searches for any modules you try to import: PYTHONPATH是python搜索您尝试导入的任何模块的地方:

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

As the error message says: 正如错误消息所示:

ValueError: Attempted relative import in non-package

The solution to this is to create a package, and have your script execute with that package in its path. 解决方案是创建一个包,让脚本在其路径中使用该包执行。

You already have a package, as you have the __init__.py files in those directories; 你已经有了一个包,因为你在这些目录中有__init__.py文件; but you only have that package in your path when you are calling it from the project directory, as you mentioned; 但是,正如您所提到的,当您从项目目录中调用它时,您只在路径中包含该包; that's because . 那是因为. is in your Python path by default. 默认位于Python路径中。

To fix this, just add the project directory to your Python path, and then invoke it with python -m outer_module.inner_module.myscript : 要解决此问题,只需将项目目录添加到Python路径,然后使用python -m outer_module.inner_module.myscript调用它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM