英文:
Why does a Groovy script hang indefinitely after throwing an exception using the assert statement?
问题
我有一个 verify.groovy
脚本,使用 evaluate()
函数执行多个 Groovy 脚本。其中一个脚本,first-check.groovy
,使用 assert
语句故意引发异常。然而,verify.groovy
脚本似乎无限期地挂起,而不是以错误消息优雅地退出。
这是 verify.groovy
的代码:
[
'first-check.groovy',
'second-check.groovy'
].each {
evaluate(basedir.toPath().resolve(it).toFile())
println String.format('验证 %s - OK', it)
}
以及 first-check.groovy
的代码:
assert 1 == 2
true
异常:
在线程 "main" 中的异常:
Assertion failed:
assert 1 == 2
|
false
at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:432)
<--- 在此挂起,直到我通过 Ctrl+C 或 command+C 中断进程
为什么脚本不是以错误消息完成,而是无限期地挂起?我该如何修复它?
英文:
I have a verify.groovy
script that executes multiple Groovy scripts using the evaluate()
function. One of the scripts, first-check.groovy
, intentionally throws an exception using the assert
statement. However, instead of exiting gracefully with the error message, the verify.groovy
script seems to hang indefinitely and never completes.
Here's the code for verify.groovy
:
[
'first-check.groovy',
'second-check.groovy'
].each {
evaluate(basedir.toPath().resolve(it).toFile())
println String.format('Verified with %s - OK', it)
}
And the code for first-check.groovy
:
assert 1 == 2
true
Exception:
Exception in thread "main" Assertion failed:
assert 1 == 2
|
false
at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:432)
<--- Hang here until I interrupt the process by Ctrl+C or command+C
Why does the script hang indefinitely instead of completing with the error message, and how can I fix it?
答案1
得分: 2
在each
和类似方法中的异常处理很棘手,所以你必须手动捕获并重新抛出异常:
String first = '''\
assert 1 == 2
true'''
String second = '''\
assert true
true'''
[ first, second ].eachWithIndex{ it, ix ->
try{
def res = evaluate it
println "Verified $ix with $res"
}catch( Throwable t ){
println "Check $ix failed miserably: $t"
throw t // << 重新抛出!
}
}
println 'end reached'
在这种情况下,你将在控制台中看到以下输出:
Check 0 failed miserably: Assertion failed:
assert 1 == 2
|
false
Assertion failed:
assert 1 == 2
|
false
at Script1.run(Script1.groovy:1)
at Script1$_run_closure1.doCall(Script1.groovy:10)
at Script1.run(Script1.groovy:8)
如果你注释掉重新抛出的那行,输出将会是:
Check 0 failed miserably: Assertion failed:
assert 1 == 2
|
false
Verified 1 with true
end reached
话虽如此,更好的迭代脚本的选项是使用普通的for
循环:
int ix = 0
for( it in [ first, second ] ){
def res = evaluate it
println "Verified $ix with $res"
ix++
}
在这种情况下,异常将被传播而不会阻塞。
英文:
The exception handling in each
and alike methods is tricky, so you have to catch and re-throw the exception manually:
String first = '''\
assert 1 == 2
true'''
String second = '''\
assert true
true'''
[ first, second ].eachWithIndex{ it, ix ->
try{
def res = evaluate it
println "Verified $ix with $res"
}catch( Throwable t ){
println "Check $ix failed miserably: $t"
throw t // << re-throw!
}
}
println 'end reached'
In this case you will see this in the console:
Check 0 failed miserably: Assertion failed:
assert 1 == 2
|
false
Assertion failed:
assert 1 == 2
|
false
at Script1.run(Script1.groovy:1)
at Script1$_run_closure1.doCall(Script1.groovy:10)
at Script1.run(Script1.groovy:8)
If you comment the re-throw line out, the output will be:
Check 0 failed miserably: Assertion failed:
assert 1 == 2
|
false
Verified 1 with true
end reached
With that said, the better option to iterate through the scripts would be to use a plain for
loop:
int ix = 0
for( it in [ first, second ] ){
def res = evaluate it
println "Verified $ix with $res"
ix++
}
In this case the exception with be propagated without blocking.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论