如何从Python脚本传递变量到Bash脚本

18
我有一个bash脚本a.sh,在其中调用了python脚本b.py。python脚本进行一些计算,我希望它返回一个值,这个值将在a.sh中稍后被使用。我知道可以这样做:
var=`python b.py`
在b.py文件中:
print x # when x is the value I want to pass

但这样不太方便,因为我也在b.py中打印其他消息。

有没有更好的方法呢?

编辑:

现在我所做的就是

var=`python b.py | tail -n 1`

这意味着我可能在b.py里打印很多东西,但是只有最后一行(最后一个print命令,假设它不包含“\ n”)会被存储在变量var中。

谢谢所有的回答!


2
也许你可以 不要 从批处理脚本开始 - 一切都从Python开始,从那里数据和代码之间的区分总是清晰的,你不必为了读取标量值(像下面使用“cat”的答案)而生成新过程,等等。 - jsbueno
8个回答

12
我会将其打印到在命令行上选择的文件中,然后我将使用类似于 cat 的东西在 bash 中获取该值。
所以你需要这样做:
python b.py tempfile.txt
var=`cat tempfile.txt`
rm tempfile.txt

[编辑,受其他答案启发的另一种想法]

你的另一个选择是精心格式化输出,这样你就可以使用像head/tail这样的bash函数,将第一/最后几行导入到下一个程序中。


:-) 虽然我认为这并不丑陋。将信息保存在文件中正是文件的用途。这样做可以更轻松地调试多程序解决方案中的问题。 - Chris Pfohl
1
也许“丑陋”这个词太过强烈了……我认为文件更适合长期存储数据。将某些东西写入磁盘,然后在毫秒级别内读取它作为在概念上是单个程序的数据传递方式,对我来说似乎不太优雅(这显然应该是 RAM 的工作吧?)。在进行文件 I/O 时还有大约 100 亿个问题可能会出现(虽然公平地说,通常情况下一切都完美无缺)。另一方面,它确实有效!(同时其他选择就更不堪了(或者更加复杂)——在 Bash 中进行 IPC,有人想试试吗?) - Cameron
@Cameron:IPC?命名管道、进程替换和(在Bash 4中)协程。 - Dennis Williamson
@Dennis:感谢提供这些信息(我只听说过命名管道),但我的观点是,与这些技术相比,进行文件I/O更容易(尽管它们可能很强大)。 - Cameron

4
我相信答案是:
.py
import sys 
a=['zero','one','two','three'] 
b = int(sys.argv[1]) 
###your python script can still print to stderr if it likes to 
print >> sys.stderr, "I am no converting" 
result = a[b] 
print result

.sh

#!/bin/sh 

num=2 
text=`python numtotext.py $num` 
echo "$num as text is $text" 

2
在您的Python脚本中,将其他消息重定向到stderr,并将x打印到stdout:
import sys
...
print >>sys.stderr, "another message"
print x

在Bash脚本中:

...
var=`python b.py 2>/dev/null`

另外,如果x是介于0和255之间的整数,您可以使用退出代码将其传递给bash:

import sys
...
sys.exit(x)

在Bash中:

python b.py
var=$?

请注意,退出代码用于指示错误,0表示无错误,这违反了惯例。

这是我的另一个想法。我决定使用文件更加“正确”,因为根据我从 OP 中了解到的情况,其他消息并不都足够“错误”。 - Chris Pfohl
标准错误流(stderr)适用于消息... - Jiří Baum

1

我不确定"better"这个词是否合适,但是您可以将结果写入文件,然后在Bash中读取并删除。

这肯定很丑陋,但如果没有其他方法可行的话,这是需要考虑的。


1

在Bash中,反引号可以使用。

我通常会做一些类似的操作:

PIP_PATH=`python -c "from distutils.sysconfig \
import get_python_lib; print(get_python_lib())"`


POWELINE_PATH=$PIP_PATH"/powerline"
echo $POWELINE_PATH

0

你可以将输出写入临时文件,并让 shell 读取并删除该文件。这甚至更不方便,但保留了 stdout 与用户的通信。

或者,你可以使用某种格式来处理 stdout:前 n 行是某些变量,其余部分将由父 shell 回显给用户。虽然也不太方便,但避免了使用临时文件。


0
最好将Python脚本中的打印值转发到临时文件,然后再将其分配给Bash值。我相信如果是这种情况,就没有必要删除该文件。
!#/bin/bash
python b.py > tempfile.txt
var=`cat tempfile.txt`

然后,获取该值:

echo $var

1
这个答案本质上与已经被接受的答案相同。如果这个答案对您有帮助,您可以通过投票来分享您的反馈! - Register Sole

0
在shell脚本中,您可以像这样使用:python_ret=$(python b.py)。它包含来自Python文件b.py的所有打印消息。然后,您可以搜索您要查找的字符串。例如,如果您正在寻找“异常”,则可以像这样进行操作:
if [[ $python_ret == *"Exception:"* ]]; then
    echo "Got some exception."
    exit 1
fi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接