[英]Handling specific Python error within Bash call?
I am using the line_profiler
, which allows you to drop @profile
decorators anywhere in a python codebase and returns line output. 我正在使用
line_profiler
,它允许您在Python代码库中的任何位置放置@profile
装饰器,并返回行输出。
However, if you try to execute python code that contains one such @profile
decorator without loading this line_profiler
module, the code will fail with a NameError, for such a decorator is defined and injected by this external library. 但是,如果您尝试执行包含一个此类
@profile
装饰器的python代码而不加载该line_profiler
模块,则该代码将失败,并出现NameError,因为此类装饰器是由此外部库定义和注入的。
I'd like a bash command that attempts to run my python script with vanilla python. 我想要一个bash命令,尝试使用香草python运行我的python脚本。 Then, if and only if the error consists of
NameError
, I want to give it a second try. 然后,当且仅当错误包含
NameError
,我才想再次尝试一下。 This is what I have got so far: 到目前为止,这是我得到的:
python -u $file || python -m kernprof -l -v --outfile=/dev/null $file"
The problem is of course that if my python code has ANY errors at all, be it ValueError
or IndentationError
or anything, it tries the profiler. 问题当然是,如果我的python代码根本没有任何错误,无论是
ValueError
还是IndentationError
或其他任何错误,它都会尝试探查器。 I want to ONLY run the profiler if the error contains a string NameError: name 'profile' is not defined
is found within stderr
. 如果错误包含字符串
NameError: name 'profile' is not defined
我只想运行探查器NameError: name 'profile' is not defined
在stderr
NameError: name 'profile' is not defined
找到NameError: name 'profile' is not defined
。
Wouldn't be better to monkey patch profile when no line_profiles is present ? 没有line_profiles时,猴子补丁配置文件会更好吗?
Something like 就像是
try:
import line_profiles
except:
import warnings
warnings.warn("Profile disabled")
def profile(fn):
def wrapper(*args, **kw):
return fn(*args, **kw)
return wrapper
This way your code runs in either case without complicating matters. 这样,无论哪种情况,您的代码都可以运行而不会使事情复杂化。
Here's a usable Bash solution that preserves stdout
and stderr
as separate streams (with the caveat that stderr
appears after stdout
) and only checks stderr
for the error message (which probably is overkill though). 这是一个可用的Bash解决方案,它将
stdout
和stderr
保留为单独的流(带有警告, stderr
在stdout
之后出现),并且仅检查stderr
是否显示错误消息(尽管这可能是过大的)。
It goes the easy route and simply saves the stderr
output to a file. 它很简单,只需将
stderr
输出保存到文件即可。 It also handles script names that contain spaces (by properly quoting variable expansions where needed) and/or start with -
(by passing --
before the filename to switch off flag processing) as it's an OCD pet peeve of mine. 它还处理包含空格的脚本名称(通过在需要的地方适当地引用变量扩展名)和/或以
-
开头(通过在文件名前传递--
以关闭标志处理),因为它是我的OCD petpeeve。
On success or if there is an error that is not the expected error, the stderr
of the first python
command is shown. 成功执行后,或者如果出现的错误不是预期的错误,则显示第一个
python
命令的stderr
。 Otherwise (for the expected error), it is hidden. 否则(针对预期的错误)将被隐藏。
Usage is $ ./check <script>
. 用法是
$ ./check <script>
。
#!/bin/bash
if [[ $# -ne 1 ]]; then
echo "Expected one argument: the script" >&2
exit 1
fi
script=$1
if [[ ! -e $script ]]; then
echo "'$script' does not exist or is not a regular file" >&2
exit 1
fi
if ! python -- "$script" 2>saved_stderr &&
grep -q "NameError: name 'profile' is not defined" saved_stderr; then
# Try again with the kernprof module.
python -m kernprof -l -v --outfile=/dev/null -- "$script"
else
# Either success or an unexpected error. Show stderr.
cat saved_stderr >&2
fi
rm saved_stderr
To check if the return status of a command is zero (ie, success), it suffices to do 要检查命令的返回状态是否为零(即成功),只需执行
if <cmd>; then <if successful>; fi`
!
negates the exit status, so if ! <cmd> ...
否定退出状态,所以
if ! <cmd> ...
if ! <cmd> ...
can be used to check for failure. if ! <cmd> ...
可用于检查故障。 !
only applies to the python
command above, not all of python ... && grep ...
. 仅适用于上述
python
命令,不适用于python ... && grep ...
。
>&2
redirects stdout
to stderr
. >&2
将stdout
重定向到stderr
。 (It's the same as 1>&2
but saves a single character, which is a bit silly, but I included for illustrative purposes as it's a common idiom.) (它与
1>&2
相同,但是保存了一个字符,这有点愚蠢,但是出于说明目的,我将其包括在内是因为这是一个常见的习惯用法。)
Creating a simple Python wrapper would seem a lot more straightforward, because inside Python, you have access to the things which go wrong. 创建一个简单的Python包装器似乎要简单得多,因为在Python中,您可以访问出现问题的地方。
Assuming your $file
uses the common __name__ == '__main__'
idiom something like this: 假设您的
$file
使用通用的__name__ == '__main__'
惯用法,如下所示:
if __name__ == '__main__':
main()
you can create a wrapper something like 你可以创建一个包装像
import yourfile
try:
file.main()
except NameError:
import kernprof
# hack hack, quickly constructed from looking at main() in kernprof.py
prof = kernprof.ContextualProfile()
execfile_ = execfile
ns = locals()
try:
prof.runctx('execfile_(%r, globals())' % (yourfile,), ns, ns)
finally:
prof.print_stats()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.