我有一个在其中调用Python的shell脚本。
#! /bin/bash
shopt -s extglob
echo "====test===="
~/.conda/envs/my_env/bin/python <<'EOF'
import sys
import os
try:
print("inside python")
x = 2/0
except Exception as e:
print("Exception: %s" % e)
sys.exit(2)
print("at the end of python")
EOF
echo "end of script"
如果执行此操作,则下面的行仍会打印出来。
"end of script"
我想在python脚本的异常块中退出外壳,并让脚本不到达EOF
是否有一种方法可以在上面的subprocess
块中创建并杀死except
,从而杀死整个shell脚本?
我可以生成一个虚拟子进程并通过杀死整个shell脚本在其中的异常块中杀死它吗?
任何例子都会有帮助。 预先感谢。
答案 0 :(得分:3)
整个EOF ... EOF
块在Python运行时中执行,因此退出它不会影响bash脚本。如果您想停止进一步的bash脚本进度,则需要收集退出状态并在Python执行后检查它,即:
#!/bin/bash
~/.conda/envs/my_env/bin/python <<'EOF'
import sys
sys.exit(0x01) # use any exit code from 0-0xFF range, comment out for a clean exit
print("End of the Python script that will not execute without commenting out the above.")
EOF
exit_status=$? # store the exit status for later use
# now lets check the exit status and see if python returned a non-zero exit status
if [ $exit_status -ne 0 ]; then
echo "Python exited with a non-zero exit status, abort!"
exit $exit_status # exit the bash script with the same status
fi
# continue as usual...
echo "All is good, end of script"
答案 1 :(得分:1)
在shell脚本中,您有2个选择:
set -e
:所有错误均退出脚本(此处有更多详细信息:Aborting a shell script if any command returns a non-zero value?)
现在,如果您不想更改shell脚本的处理方式,则可以获取python脚本的父进程并杀死它:
except Exception as e:
import os,signal,sys
print("Exception: %s" % e)
os.kill(os.getppid(),signal.SIGTERM)
sys.exit(2)
如果您在Windows上需要此功能,则此功能将不起作用(os.kill
不存在),您必须对其进行调整以调用taskkill
:
subprocess.call(["taskkill","/F","/PID",str(os.getppid())])
现在我要说杀死父进程是一种不好的做法。除非您不控制此父进程的代码,否则应尝试优雅地处理退出。
答案 2 :(得分:0)
杀死整个脚本的一种方法是保存PID,然后在异常发生时使用Python的系统命令在PID上执行kill命令。如果我们导入了“ os”,它将类似于:
initializeForm() {
this.formGroupItemSelection = this.fb.group({
refNumber : new FormControl(true),
partNumber: new FormControl(false),
itemName: new FormControl(false),
manufacturerName: '',
refNumberSelected:[
null,
Validators.compose([Validators.required, matchValuesRefNumber(this.listOfItems)])
],
partNumberSelected:[
null,
Validators.compose([Validators.required, matchValuesPartNumber(this.listOfItems)])
],
itemNameSelected: [
null,
Validators.compose([Validators.required, matchValuesItemName(this.listOfItems)])
],
manufacturerNameSelected:[
null,
Validators.compose([Validators.required, matchValuesManufacturerName(this.listOfItems)])
]
})
//This will set the radio button checked no need to add checked attribute you can set cheked dynamically
this.formGroupItemSelection.get('refNumber ').setValue(true);
this.formGroupItemSelection.get('partNumber').setValue(true);
this.formGroupItemSelection.get('itemName').setValue(true)
}