How to pass an error exit code from a python script to the KSH script that calls it?
我有一个由KornShell脚本调用的python脚本。如果python脚本遇到错误,korn shell脚本仍然以0退出。如何让python脚本告诉ksh它没有正确终止?
说唱脚本如下:
1 2 3 4 5 6 7 8
| python2.7 python_script.py ${inargument} >> ${log_file} 2>&1
exit_code=$?
if [ ${exit_code} -ne 0 ]
then
echo"Python script failed">> ${log_file}
fi |
- 在shell脚本中,您可以执行echo"Returncode=$?"。
- 你能展示一下你的shell脚本吗?如果shell脚本的最后一个命令运行python脚本,则shell应以与出错时python脚本相同的退出状态退出。(如果在调用python脚本之后有任何内容,例如在shell中有一条日志语句,那么它可能是返回该行的退出状态)。
- @CharlesDuffy我添加了shell脚本的细节。它应该捕获.py脚本的退出状态,但我似乎忽略了一些内容。
- @亚历克希曼,从壳的角度看很好。要进行测试,请尝试用python2.7 -c 'raise Exception("foo")'替换python2.7 python_script.py--如果您的shell脚本突然看到非零退出状态,您知道是python代码掩盖了真正的退出状态。
- @Alexkinman,…好吧,"好"是一个延伸;当你只测试这些时,捕捉退出状态是不好的做法;最好这样写:if ! python2.7 python_script.py ...; then echo"Python script failed"; fi,而不是捕捉$?。但是,如果Python脚本屏蔽了它的退出状态,这也不会起作用。
- 顺便说一句,不是把>> ${log_file}放在每个命令的末尾,而是把exec >>"$log_file"(可能还有2>&1)放在脚本的顶部,这将永久地进行重定向;这样,您就不会在多个单独的时间重新打开文件。
- 投票以不可生产的方式结束。标准的python安装返回异常的非零退出状态。当ctrl-c中断时,python -c 'raise ValueError("boom"); echo $?打印1和python -c 'import time; time.sleep(3600)'同样返回1的退出状态。也许您的python2.7命令是一个写不好的包装器,它丢弃了退出状态。
- @Alexkinman,如果你在创建的目录下运行EDOCX1/gist.github.com/charles dyfis net/…,并运行ksh test.ksh,你的结果是否不包含"python script failed"?
- @CharlesDuffy我确实得到了"python脚本失败"
- @Alexkinman,…如果您的shell脚本成功地检索到了python脚本的非零退出状态,这就是您希望和期待的。你能更新你的测试用例来显示一种情况吗?
- @我用另外一个脚本解决了这个问题。谢谢你的帮助。这个问题可以解决。
- @Alexkinman,…作为它的创建者,你应该能够自己删除这个问题——我们不需要等待另外三个人投票。
- @Charlesduffy下面的答案仍然有一些有用的信息,如果我删除这个问题(不是为了我的利益,而是为了其他搜索),这些信息就会消失,我是正确的吗?
- 我不确定这里是否有内容没有在回答更狭隘的问题时更为简洁和直接地涵盖(因此,它可能更容易被感兴趣的人发现)。例如,stackoverflow.com/questions/14259660/…;stackoverflow.com/questions/25728287/…;等等。
- @查尔斯达菲,我不能删除这个问题,因为它已经有答案了。
- 啊——这些规则往往会随着时间和代表级别的变化而变化,所以很难跟踪它们对每个人都是什么。我们很快就会得到第五次近距离投票。
我不确定ksh,但这就是让python返回非零返回值的方法,我假设ksh可以检测并处理这个问题。
1 2 3 4
| import sys
retCode = 5
sys.exit(retCode) |
或
1 2
| retCode = -128
raise SystemExit(retCode) |
- -128在这里无效——它只是无符号单字节整数,因此它将被转换为其他类型,而不是原封不动地返回。
- …而且,在这方面,ksh的行为与任何其他符合POSIX的shell的行为完全相同,用先前命令的退出状态填充$?。
- (另一方面,有关常规出口状态代码的列表,请参阅man 3 sysexits;根据惯例,自定义值应低于64的EX__BASE常数,对于错误状态,应高于c99中定义的0(EXIT_SUCCESS常数)。
我不能评论,因为声誉,但您绝对可以使用来自nephim comment的代码。
1)只需将nephim的第一个代码放入test.py。(chmod 700 test.py)
2)此ksh脚本run test.py:
1 2 3 4 5
| #!/usr/bin/ksh
./test.py
exit $? |
3)这是来自命令行的示例
1 2 3
| > ./test.ksh
> echo $?
5 |
附言:你也应该做一个测试。
P.P.S:可能我误解了你的问题。如果您的python脚本在到达末尾之前退出(因此它不执行sys.exit(coderet)命令),在这种情况下,您应该使用try..execpt构造。
1 2 3 4
| try :
<some code>
except <Error to Catch>:
sys.exit(codeRet) |
正如这里所解释的:python:关于捕获任何异常,您甚至可以捕获所有异常:
1 2 3 4
| try:
do_something()
except:
print"Caught it!" |
但正如所解释的:"你可以,但你不应该"
更新:@ AlexKinman我觉得你的Python有点问题…正如三重皮提到的,它可以是包装纸吗?你能给我一份埃多克斯的退货单吗?
这里是我的测试:
$# cat wrong_test.ksh
1 2 3 4 5 6 7 8 9 10 11 12
| #!/bin/ksh
log_file=log.txt
python -c 'raise Exception("foo")' >> ${log_file} 2>&1
exit_code=$?
if [ ${exit_code} -ne 0 ]
then
echo"Python script failed">> ${log_file}
fi |
$# cat log.txt
Traceback (most recent call last):
File"", line 1, in
Exception: foo
Python script failed
$# cat good_test.ksh
1 2 3 4 5 6 7 8 9 10 11 12
| #!/bin/ksh
log_file=log1.txt
python -c 'print"Hello"' >> ${log_file} 2>&1
exit_code=$?
if [ ${exit_code} -ne 0 ]
then
echo"Python script failed">> ${log_file}
fi |
$# cat log1.txt
Hello
- 如果解释器由于异常而退出,那么默认情况下它将具有非零的退出状态——您不需要捕获它并自己调用sys.exit()。
- …你可以很容易地自己测试:python -c 'raise Exception("foo")'; echo $?。
- @CharlesDuffy问题是我没有得到非零默认退出状态。当我在Python解释器中运行代码时,如果传递错误的输入参数,我会得到一个错误。但当我使用ksh时,它不会传递任何东西给ksh。
- @查尔斯达菲…是的,你是对的。在这种情况下,一网打尽只发送系统出口(1)不使传感器…除了在代码中使用退出状态1的情况。在这种情况下,捕捉并发送另一个状态可能是Intrusting。
- @Alexkinman,你做过我提议的测试吗?如果没有,您就不知道问题是在您的Python中还是在您的shell中;如果是前者,那么这个问题——作为一个整体——就是在问错误的事情。
- @查尔斯达菲,我做了,问题似乎在外壳,而不是Python。
- @Alexkinman,…你能修改这个问题来展示如何重现这个决定吗?我无法谴责这种行为;三倍都没有;保罗(据我所知)也没有(根据他们最近在这方面的评论)。
- @CharlesDuffy是的,对我来说,它返回了好的返回代码:$>python-c'引发异常("foo")';echo$?回溯(最近调用的最后一个):file"",line 1,inexception:foo 1--------------------$>python-c'print"hello"';echo$?你好0,如果有异常,我有没有异常代码0的代码1
- @Alexkinman,…鉴于上述情况,您是否可以修改为提供明确的复制步骤,以便其他人可以使用相同的代码并做出相同的决定(关于壳牌的行为是否存在缺陷)?
- @查尔斯达菲,我解决了这个问题。python运行得很好,ksh也运行得很好,但是它下游的另一个ksh有一个bug,使我的代码看起来在实际运行时不能正常工作。谢谢你的帮助。
将整个脚本包装在一个try块中,然后在catch中将错误写入输出文件。比起在ksh中,您可以读取输出文件,并做任何您需要做的事情。
这是一些伪代码。
1 2 3 4 5
| rm opFile
python yourSript.py
if opFile != blank:
process log file...
start cat runlog.m | more |
- 哦,这对你没用?
- 我不能代表第一个投反对票的人发言,但我自己说,这不是一个问题,它是否起作用:有一种标准的实践方法可以做到这一点,并且忽略了那个惯例(在c99标准、posix标准和其他标准中定义的),因为没有好的理由是……嗯,不是很好的练习。
- +@Nephlm提供了最好的答案,在一个用例中,ksh希望使用python优雅地失败,可能在失败之前尝试多种方法,据我所知,创建一个记录执行路径的运行日志文件是标准实践…(问题是我不知道。)
- 是的,日志记录是标准做法。不,使用记录的内容代替退出状态不是标准做法。