bash 在shell脚本中捕获python脚本抛出的异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24207916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Catching the exception thrown by python script in shell script
提问by Codelearner
I am having a shell script which opens a file and pass it to python script for processing it. So if there is any issue with the file ( e.g. the file content is not in the format required for the successful execution for python script), the python script throws an exception. Since my objective it to process N files using python script. I need to know which is the file causing the script to break. I read on how to catch the exception in thrown by command execution. http://linuxcommand.org/wss0150.php. But in my case its the python script which throws the exception and I need to know in shell script what the exception has been thrown. Can anyone help me how can I proceed with this?
我有一个 shell 脚本,它打开一个文件并将其传递给 python 脚本进行处理。因此,如果文件有任何问题(例如,文件内容不是成功执行 Python 脚本所需的格式),则 Python 脚本将引发异常。由于我的目标是使用 python 脚本处理 N 个文件。我需要知道哪个文件导致脚本中断。我阅读了如何捕获命令执行引发的异常。http://linuxcommand.org/wss0150.php。但在我的情况下,它是抛出异常的 python 脚本,我需要在 shell 脚本中知道抛出了什么异常。任何人都可以帮助我如何继续进行此操作?
Below is the code snippet :
下面是代码片段:
#!/bin/bash
yesterday=$(date --date "yesterday" "+%y%m%d")
ftoday=$(date --date "today" "+%m-%d-%Y")
year=$(date "+%Y")
fileList=$(find C:/logdata/$year/$ftoday/ -iname "*"$yesterday".log")
for var in $fileList
do
echo -e "\n START Processing File : $var" >> shelltestlog.txt
cat $var| ./scriptA.py
echo -e "\n END Processing File : $var" >> shelltestlog.txt
done
采纳答案by konsolebox
If your python script returns an non-zero error level whenever it gets an exception, you can use || { }
to log messages:
如果您的 python 脚本在遇到异常时返回非零错误级别,您可以使用|| { }
记录消息:
./scriptA.py < "$file" || {
printf "\n Python script scriptA.py failed with file \"%s\".\n" "$file" >> shelltestlog.txt
}
I actually tried to simplify your code first:
我实际上试图首先简化您的代码:
#!/bin/bash
yesterday=$(date --date "yesterday" "+%y%m%d")
ftoday=$(date --date "today" "+%m-%d-%Y")
year=$(date "+%Y")
readarray -t filesList < <(find C:/logdata/$year/$ftoday/ -iname "*"$yesterday".log")
for file in "${filesList[@]}"; do
printf "\n START Processing File : %s\n" "$file" >> shelltestlog.txt
./scriptA.py < "$file" || {
printf "\n Python script scriptA.py failed with file \"%s\".\n" "$file" >> shelltestlog.txt
}
printf "\n END Processing File : %s\n" "$file" >> shelltestlog.txt
done
回答by chepner
An uncaught exception will produce a traceback printed to standard error. The best you can do is capture that, and try to parse it.
未捕获的异常将产生打印到标准错误的回溯。您能做的最好的事情就是捕获它,并尝试解析它。
if ! ./scriptA.py < "$var" 2> stderr.txt; then
# Parse stderr.txt to see what exception was raised.
fi
回答by zwol
You should rewrite the shell script in Python and merge it into the existing Python script.
The stuff that you are currently doing with the date
command, can be done with the datetime
and time
modules. The stuff you are doing with find
can be done with os.walk
and fnmatch.fnmatch
.
您应该用 Python 重写 shell 脚本并将其合并到现有的 Python 脚本中。您当前使用date
命令执行的操作可以使用datetime
和time
模块完成。你正在做的事情find
可以用os.walk
和来完成fnmatch.fnmatch
。
Here's an outline:
这是一个大纲:
#! /usr/bin/python
def scriptA(file_to_process):
# the code currently in scriptA goes here;
# modify it to read from `file_to_process` rather than `sys.stdin`
def get_file_list():
# your bash logic to construct the file list goes here,
# converted to Python as suggested above
def main():
for filename in get_file_list():
sys.stderr.write("Processing {}...\n".format(filename))
try:
scriptA(open(filename, "rt"))
except SomeExceptionType as e:
# handle exception...
except SomeOtherExceptionType as e:
# handle other kind of exception...
sys.stderr.write("Done processing {}.\n".format(filename))
main()
回答by glenn Hymanman
You can play some redirection games:
你可以玩一些重定向游戏:
# open file descriptor 3, pointing to the same destination as stdout
exec 3>&1
# run the script,
# python's stderr goes to stdout so it can be captured in a variable
# python's stdout goes to file descriptor 3, displayed on the terminal
python_stderr=$( ./scriptA.py < "$var" 2>&1 1>&3 )
# close the file descriptor
exec 3>&-
Then you can examine $python_stderr for patterns
然后你可以检查 $python_stderr 的模式
case $python_stderr in
"") echo "nothing on stderr" ;;
*foo*) handle_foo_error ;;
*bar*) handle_bar_error ;;
*baz*) handle_baz_error ;;
esac