【问题标题】:Propagate python script exit code to calling shell script将 python 脚本退出代码传播到调用 shell 脚本
【发布时间】:2018-10-07 00:15:14
【问题描述】:

如果有任何失败,我在 python 脚本(使用 python 3.4)中有以下内容:

exit(1)

这个python脚本的目的是给print()一些值,这样它就可以像这样分配给一个shell变量:

#!/bin/bash
set -e
result=$(python my-script.py)
echo $?

但是,如果脚本失败,上面的 echo 返回 0。如果 python 脚本失败(即返回非零退出代码),我希望 set -e 立即中断脚本并使脚本失败。

我怎样才能做到这一点?我也在我的 bash 脚本中尝试了set -eo pipefail,但我发现没有任何区别。

我正在运行 Ubuntu 15。

编辑

我的python脚本(逐字)以防万一它是这里的嫌疑人......

import re
import sys

version_regex = r'(?:(?:release|hotfix)\/|^)([\d.]+)-\d+-g[a-f\d]+$'

result = re.search(version_regex, sys.argv[1])
if not result:
    exit(1)

print(result.group(1))

请注意,我在实验中尝试了 sys.exit(1)exit(1),但我从未见过我的 bash 脚本失败。

编辑 2

parsed_version=$(python parse-git-describe.py $describe_result; echo $?)
echo $parsed_version
echo $?

上面的 bash 脚本给了我以下输出:

1
0

注意脚本parse-git-describe.py和之前提供的python脚本是一样的。

编辑 3

显然local 导致此中断。上面的 EDIT 2 是错误的,即在 shell 函数中使用 local 的结果:

foo()
{
    local parsed_version=$(python parse-git-describe.py $describe_result; echo $?)
    echo $parsed_version
    echo $?
}

结果是:

1
0

但如果我删除 local 会正常吗?

foo()
{
    parsed_version=$(python parse-git-describe.py $describe_result; echo $?)
    echo $parsed_version
    echo $?
}

结果是:

1
1

为什么local 很重要?

【问题讨论】:

  • this SO 帖子。提到 set -e 是不可靠和不好的做法。您的脚本不一定能到达echo
  • 由于您直接使用exit,请尝试将您的导入更改为from sys import exit
  • 我已经阅读了那篇文章,我知道人们建议trap,但我不确定如何在我的具体情况下使用它。
  • @ray 我对 python 中的sys.exit() 的理解是它用于“应用程序”,而exit() 用于交互式外壳(这是我的情况)
  • 您的脚本以local: can only be used in a function 结束。

标签: python bash shell


【解决方案1】:

如果您通过调用sys.exit(code) 完成脚本,您可以设置退出代码。

【讨论】:

  • 我已经这样做了...我将使用 python 脚本逐字更新我的帖子
  • 您正在使用内置的exit。将您的exit(1) 更改为sys.exit(1) 或按照@ray 提到的操作并将from sys import exit 添加到脚本的顶部。
  • 为什么重要?我读过这两个退出调用最终都会调用相同的东西。我在我的实验中都尝试了它们,但我没有注意到有什么不同。
【解决方案2】:

local 只能在 bash 的函数中使用。 (所以你上面的 bash 脚本代码也不起作用。)

为什么不在 bash 脚本中调用你的 python 脚本并检查返回值,然后在必要时跳出你的脚本?

$ python -c "exit(0)"
$ [ $? == 0 ] || echo "fail"
$ python -c "exit(1)"
$ [ $? == 0 ] || echo "fail"
fail

我猜你可以很容易地在你的 shell 脚本中调整它。

【讨论】:

  • 实际上我的 bash 代码是一个函数的复制和粘贴,我把它拼凑在一起来解决我的问题。小疏忽,我会改正的。在我真正的脚本思想中,我实际上并没有在函数之外使用local
  • 更好、更惯用的方法是python -c 'exit(1)' || echo "fail"
  • 我建议在你的 bash 脚本中也将错误代码传递给调用函数,然后根据它滑出脚本。
  • @tripleee 我只是想让提问者更清楚如何将返回值传递给调用 bash 脚本...
  • @ferdy 我在问题中编写的 bash 脚本本质上是在测试同一件事。我的 echo 调用返回 0,而不是 1。
【解决方案3】:

为什么local 很重要??

local 关键字指定变量的范围。以下示例脚本应说明:

#!/bin/bash
HELLO=Hello    # global variable, HELLO

function hello {
    local HELLO=World   # local variable with same name; diff scope
    echo $HELLO         # this is the local, not global!
}

echo $HELLO  # print global
hello        # function call!
echo $HELLO  # global unchanged!

从 shell(放置在 test.sh 脚本中)运行此代码会产生:

➜  Projects  ./test.sh
Hello
World
Hello

当您使用local 时,当函数返回给调用者时,变量及其退出代码超出范围。如果您不希望这种情况发生,您的函数应该将值返回给调用者。

【讨论】:

  • 再一次,你仍然没有理解我的意思。请参阅我放在这里的示例。请注意,local 关键字改变了能够检测退出代码的行为。 goo.gl/1J4IB1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-26
  • 2011-11-26
  • 2020-10-02
  • 1970-01-01
  • 2019-10-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多