【问题标题】:In Python: how can I get the exit status of the previous process run from Bash (i.e. "$?")?在 Python 中:如何获取从 Bash 运行的前一个进程的退出状态(即“$?”)?
【发布时间】:2014-10-29 09:29:18
【问题描述】:

我有一个 Python 脚本,它应该报告上一个命令的成功或失败。目前,我正在做

command && myscript "Success" || myscript "Failed"

我想做的是能够运行未链接的命令,如下所示:

command; myscript

并让myscript 检索$?,即存在状态。我知道我可以跑:

command; myscript $?

但我真正在寻找的是一种从 Python 中检索 $? 的 Python 方法。

我该怎么做?


既然这是一个奇怪的请求,让我澄清一下它的来源。我有一个 Python 脚本,它使用 pushover API 向我的手机发送通知。

当我运行一个长进程时,我以process && notify "success" || notify "failure" 运行它。但有时我忘记这样做,只是运行该过程。此时,我想在仍在处理的命令行上运行“通知”,让它获取退出状态并通知我。

当然我也可以在 bash 中实现 pushover API 调用,但现在它变成了如何在 Python 中实现它的问题。

【问题讨论】:

  • 您是否尝试通过 call() 或其他方式显式“运行”$?
  • 这是一个非常好的问题。我一直在寻找,到目前为止还没有找到任何东西。您可以执行command; SOMEVAR=$?; myscript,然后在您的脚本中检索os.environ["SOMEVAR"],但这并不比执行command; myscript $? 好。如果我找到任何东西,我会回来回答。
  • @4rlekin 好主意,但它似乎不起作用。 print subprocess.call("/bin/echo $?", shell=True) 总是返回 0。我怀疑这是因为该命令是在一个不知道其祖父母外壳存在状态的新外壳中执行的(原始 bash 运行 python,运行 bash)
  • 取决于你想用这个脚本实现什么,愚蠢的简单解决方案是已经在 bash 中编写脚本(并从内部调用所有特定于 python 的功能)
  • 经过进一步测试,我认为是做不到的。放入cmets会有点太长的原因,所以我会给出它作为答案。

标签: python bash exitstatus


【解决方案1】:

这可能是不可能的,因为脚本(任何语言,而不仅仅是 Python)是如何执行的。试试这个:创建一个名为 retcode.sh 的 shell 脚本,其内容如下:

#!/bin/bash
echo $?

使其可执行,然后在 shell 提示符下尝试以下操作:

foo # Or any other non-existent command
echo $?  # prints 127
foo
./retcode.sh  # prints 0

我必须仔细检查这一点,但似乎 所有 脚本,而不仅仅是 Python 脚本,都在一个单独的进程中运行,该进程无法访问由“父”shell 进程运行的上一个命令。这可以解释为什么 Python 没有(据我所知)给你一种方法来检索前一个命令的退出代码,比如 bash 的 $?——因为无论如何它总是 0。

我相信你做command; myscript $? 的方法是实现你想要做的最好的方法:让 Python 脚本知道上一步的退出代码。

更新:在看到您对您正在尝试做的事情的澄清后,我认为您最好的办法是稍微修改您的 notify 脚​​本,以便它可以选择像-s--status (当然,使用argparse 使解析选项更容易)并根据状态码发送消息(如果代码为0,则为“成功”,如果是其他任何内容,则为“失败NN” ,其中NN是实际代码)。然后,当您在没有 && notify "success" || notify "failure" 小技巧的情况下键入 command 时,当它仍在运行时,您可以键入 notify -s $? 并获得您正在寻找的通知,因为这将是您的 shell 在 command 之后运行的下一件事返回。

【讨论】:

  • 谢谢。是的,你是对的,你的第一个脚本是在它自己的 bash 中运行的,它对父 bash 的退出状态一无所知。这只有在父 bash 将 $? 传递给子节点时才有效,但它不会。不过,我希望 python 可能会获得价值。这是可能的,但似乎没有做到。它相当于:command; python $? script 其中$? 在脚本中是可用的
  • 您可以通过在前面使用一个点来告诉外壳程序在当前外壳程序中运行您的命令。如。 ' . ./foo '.如果没有前面的点,它会生成一个子 shell 来运行命令
  • @Doon 好点,这当然适用于 bash 脚本一个接一个的情况。我无法获取 (.) python 虽然
  • 感谢您的更新,感谢您耐心了解我想做的事情的细节。我知道这有点吹毛求疵:) 我现在采用了您的解决方案。谢谢!
【解决方案2】:
false; export ret=$?; ./myscript2.py

myscript2.py:

#!/usr/bin/python

import os
print os.environ['ret']

输出:

1

【讨论】:

  • 感谢您的回答。不过,我试图在问题中暗示这一点。虽然您的解决方案可以工作,但现在这已经退化为一个非常挑剔的论点,即在没有任何显式参数传递的情况下从 python 获取$?。不过,两者都有很好的解决方案!谢谢
  • 我已经删除了第一个答案。
【解决方案3】:

这显然不可能:进程的退出值只能对其父级访问,并且我所知道的任何 shell 都没有提供 API 来允许下一个进程检索它。

恕我直言,更接近您的需求的是:

process
myscript $?

这样,即使您开始处理而不考虑通知,您也可以这样做。

您还可以使脚本能够运行进程获取退出代码并通知其通知,或者(取决于命令行中给出的选项)使用作为参数给出的退出代码。例如,您可以:

  • myscript process:运行 process 并发出通知
  • myscript -c $?: 只做通知

argparse 模块可以让这一切变得简单。

【讨论】:

    【解决方案4】:

    但我真正在寻找的是一种 Python 方法来检索 $?来自 Python。

    如果您将它们作为单独的进程运行,那么这显然是不可能的。

    一个独立的进程无法知道另一个进程是如何结束的。

    您可以 1) 将结果存储在文件中,2) 从 command 发出一些内容,并将其通过管道传输到脚本 3) 从 myscript 运行命令,等等...但是您需要某种交流

    最简单的方法,当然是command; myscript $?

    【讨论】:

    • 我了解进程分离,但我一直在寻找 python 自己获取 $? 并将其提供给我的脚本的机会。估计不是这样的。感谢您的澄清!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    • 2014-01-29
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多