【问题标题】:How do I pass multiple outputs of a python script to a shell bash script?如何将 python 脚本的多个输出传递给 shell bash 脚本?
【发布时间】:2021-12-13 11:34:53
【问题描述】:

我需要一个 python 脚本来计算一些数值,在下一步中,这些数值将传递给另一个 shell bash 脚本以继续以下计算。假设python脚本是./python.py,即:

import numpy as np
def func(arg1, arg2):
    ...
    result1=0.111
    result2=0.222
    result3=0.333
    return result1, result2, result3
arg1=1
arg2=2
result1, result2, result3 = func(arg1, arg2)
print(result1, result2, result3)

bash 脚本是./bash.sh,其中包含:

#!/bin/bash
...
~/.conda/envs/vegetation/bin/python split_nc_domain.py
...(following part which needs result1, result2, result3)

那么如何将result1, result2, result3 传递给./bash.sh?我知道如果我只有一个输出,我可以使用以下命令: VARIABLE=`~/.conda/envs/vegetation/bin/python split_nc_domain.py` VARIABLE=$(~/.conda/envs/vegetation/bin/python split_nc_domain.py)。但是我怎样才能为python的多个输出做到这一点呢?谢谢!


更新:

cmets 中有人建议我使用x=($(~/.conda/envs/vegetation/bin/python split_nc_domain.py))。但下一步我能做什么?有没有像x[0], x[1], x[2] 这样的东西来检查? by echo $x 我只能看到第一个值0.111 是第一个变量的值。

【问题讨论】:

  • 请将 ./python.py 的输出添加到您的问题中。
  • 通用方法是通过一个永远不会出现在值中的分隔符来分隔输出的值,然后使用bash 中的分隔符来读取值,例如IFS=<delimiter> read -r var1 var2 var3。如果你使用换行符作为分隔符,你可以在循环中使用IFS='' read -r line
  • 嗨@Cyrus,“./python.py 的输出”是什么意思?
  • 我在问题描述中添加了result1、result2和result3的示例值。它们是 float64 类型的。
  • 由于“结果”只是一堆数字,我会将它们写入标准输出(用空格分隔)。在 bash 中,您获取此输出并将数字传输到 bash 数组中。

标签: python-3.x bash shell variables


【解决方案1】:

假设您的 python 脚本无法更改,我们必须使用以下格式的 bash:

first_value second_value third_value

其中单个空格分隔三个字段。请注意,包含空格的值会破坏该格式(创建额外的字段),但在 python 打印的数字的上下文中,这似乎不太可能。

分别检索这三个值的基本方法是将整个值存储在一个文本变量中,然后执行三个命令分别检索这三个值:

whole_output="$(./python.py)"
first_value="$(echo "$whole_output" | cut -d' ' -f1)"
second_value="$(echo "$whole_output" | cut -d' ' -f2)"
third_value="$(echo "$whole_output" | cut -d' ' -f3)"

这依赖于$(command substitution),它首先被解释,执行它包含的命令,然后在执行包含它的命令之前被它的输出替换。
例如,对于第一行,首先执行您的 python 脚本,然后命令将变为 whole_output="first_value second_value third_value",这是一个基本任务。
使用的cut 命令可让您指定分隔符(此处为空格)和要检索的字段的索引。

你可以try it here

如果你有很多值,每个值写一行,每个值调用一个命令就会有问题。在这种情况下,您可以使用readreadarray,其中第一个读取多个变量,第二个读取一个数组:

IFS=' ' read -r var1 var2 var3 ... varN < <(./python.py)

readarray -d' ' array < <(./python.py)
# can access individual values with ${array[0]}, ${array[1]}, etc. 
# or list all values with ${array[@]}

您可能想知道为什么我们使用&lt; &lt;(...) 语法将数据输入到读取/读取数组中。通常,您只需使用管道即可。管道的问题在于,引用man bash,“管道中的每个命令都作为单独的进程(即在子shell中)执行。”并且子shell有自己的范围,这意味着变量的变化在管道之外是不可见的。
另一方面,&lt; &lt;(...) 语法允许您将它包含的命令的输出提供给任何命令的输入,而无需使用所谓的进程替换创建任何子 shell。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多