将Python数组传递给Bash脚本(并将Bash变量传递给Python函数)

7

我编写了一个Python模块,其中包含返回数组的函数。我希望能够访问从Python模块返回的字符串数组,并在bash脚本中迭代,以便我可以迭代数组元素。

例如:

Python模块(mymod)

def foo():
    return ('String', 'Tuple', 'From', 'Python' )

def foo1(numargs):
    return [x for x in range(numargs)]

Bash脚本

foo_array  = .... # obtain array from mymod.foo()
for i in "${foo_array[@]}"
do
    echo $i
done


foo1_array = .... # obtain array from mymod.foo1(pass arg count from bash)
for j in "${foo1_array[@]}"
do
    echo $j
done

我该如何在bash中实现这个功能?
版本信息:
Python 2.6.5 Bash: 4.1.5

将脚本中的数据输入和输出最简单的方法可能是通过标准输入/标准输出。 - Andrew Jaffe
5个回答

14

第二次尝试 - 这次 shell 承担了集成的大部分工作。

给定包含以下内容的 foo.py 文件:

def foo():
        foo = ('String', 'Tuple', 'From', 'Python' )
        return foo

然后按照以下方式编写你的Bash脚本:

#!/bin/bash
FOO=`python -c 'from foo import *; print " ".join(foo())'`
for x in $FOO:
do
        echo "This is foo.sh: $x"
done
剩下的部分是从 Python 端驱动集成的第一个答案。

Python

import os
import subprocess

foo = ('String', 'Tuple', 'From', 'Python' )

os.putenv('FOO', ' '.join(foo))

subprocess.call('./foo.sh')

bash

#!/bin/bash
for x in $FOO
do
        echo "This is foo.sh: $x"
done

感谢您的反馈。我希望我的Python模块对调用它的人/事物是不可知的(关注点分离)- 您建议的代码需要修改Python代码- 这并不理想。 - Homunculus Reticulli
@HomunculusReticulli 好的 - 希望我现在理解正确了 - 新代码使用 shell 驱动集成。 - Maria Zverina
是的!这很直观地让人感到有道理!非常感谢!我刚试了一下,它确实有效 :) - Homunculus Reticulli
顺便说一句,我猜想要将值从bash传递到Python,我需要在bash中生成字符串并使用-c选项从bash->python传递?要传递复合数据类型(例如数组),我可能需要在Python端编写包装函数以解析传递的值-我的假设是正确的,还是有更好的方法可以从bash -> python函数传递数据? - Homunculus Reticulli
@HomunculusReticulli 你的建议是可行的 - 你也可以通过环境变量传递它,像这样 python -c "import os; print os.getenv('HOME')" - Maria Zverina

1
此外,您可以告诉Python进程使用“-”来读取标准输入。
echo "print 'test'" | python -

现在,您可以定义多行Python代码片段并将它们传递到子shell中。
FOO=$( python - <<PYTHON

def foo():
    return ('String', 'Tuple', 'From', 'Python')

print ' '.join(foo())

PYTHON
)

for x in $FOO
do
    echo "$x"
done

你也可以使用 envset 命令将环境变量和本地变量从 bash 传递到 Python(作为 ".." 字符串)。


谢谢,这对我非常有帮助。 - Perlnika

0
这也有帮助。script.py:
 a = ['String','Tuple','From','Python']

    for i in range(len(a)):

            print(a[i])

然后我们制作以下bash脚本pyth.sh

#!/bin/bash

python script.py > tempfile.txt
readarray a < tempfile.txt
rm tempfile.txt

for j in "${a[@]}"
do 
      echo $j
done

sh pyth.sh


0

除了Maria使用的Python输出方法外,您还可以使用argparse库从bash向Python脚本输入变量;这里有适用于Python 3的教程和进一步的文档此处,以及适用于Python 2的此处

一个示例Python脚本command_line.py

import argparse
import numpy as np

if __name__ == "__main__":

    parser = argparse.ArgumentParser()

    parser.add_argument('x', type=int)

    parser.add_argument('array')

    args = parser.parse_args()

    print(type(args.x))
    print(type(args.array))
    print(2 * args.x)

    str_array = args.array.split(',')
    print(args.x * np.array(str_array, dtype=int))

然后,从终端运行:

$ python3 command_line.py 2 0,1,2,3,4

# Output
<class 'int'>
<class 'str'>
4
[0 2 4 6 8]

0
以逗号分隔的值列表通过命令行进行管道传输,这或许可以作为对象序列化的替代方案。
然后你可以执行以下操作:
> python script.py | sh shellscript.sh

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