TM.*_*TM. 20 python exception-handling jython
我想知道如何捕获任何凸起的对象(即一种不延伸的类型Exception),并且仍然可以获得它的引用.
我在使用Jython时遇到了这样做的愿望.在调用Java方法时,如果该方法引发异常,它将不会扩展Python的Exception类,因此像这样的块将无法捕获它:
try:
# some call to a java lib that raises an exception here
except Exception, e:
# will never be entered
Run Code Online (Sandbox Code Playgroud)
我可以这样做,但后来我无法访问引发的异常对象.
try:
# some call to a java lib that raises an exception here
except:
# will enter here, but there's no reference to the exception that was raised
Run Code Online (Sandbox Code Playgroud)
我可以通过导入Java异常类型并显式捕获它来解决这个问题,但这使得编写通用异常处理包装器/装饰器变得困难/不可能.
有没有办法捕获一些任意的异常,仍然在except块中得到它的引用?
我应该注意到,我希望我正在使用异常处理装饰器来使用Python项目,而不仅仅是Jython项目.我想避免导入,java.lang.Exception因为它只是使它成为Jython.例如,我想我可以做这样的事情(但我还没试过),但如果可以的话,我想避免它.
try:
# some function that may be running jython and may raise a java exception
except (Exception, java.lang.Exception), e:
# I imagine this would work, but it makes the code jython-only
Run Code Online (Sandbox Code Playgroud)
Bri*_*nna 36
您可以使用该sys模块引用异常.sys.exc_info是类型,实例和追溯的元组.
import sys
try:
# some call to a java lib that raises an exception here
except:
instance = sys.exc_info()[1]
Run Code Online (Sandbox Code Playgroud)
小智 9
FWIW,我发现如果你将这个导入添加到你的Jython脚本:
from java.lang import Exception
Run Code Online (Sandbox Code Playgroud)
并使用传统的Python异常处理程序:
except Exception, e:
Run Code Online (Sandbox Code Playgroud)
它会赶上两个 Python的异常和 Java异常
只是对任何感兴趣的人...我花了一些时间测试东西,因为我想找出如何获得正确的堆栈跟踪,无论是Python异常(实际上是BaseException,哪个是基类)还是java.lang.Throwable (抛出异常,错误等的java基类)...此代码说明了如何正确捕获所有行号refs.
import sys
import traceback
import java
print "hello world"
def custom_hook( type, exc, tb ):
if isinstance( sys.exc_info()[ 1 ], java.lang.Throwable ):
sys.stderr.write( "AS JAVA:\n" )
sys.exc_info()[ 1 ].printStackTrace() # java part
else:
sys.stderr.write( "NO JAVA TRACE:\n" )
sys.stderr.write( "AS PYTHON:\n" )
traceback.print_exc()
# useful for custom exception handling!
sys.excepthook = custom_hook
def handle_exc():
# generate either a java.lang.Throwable (uncomment the next line and comment out "a = 16 / 0"
# java.lang.String( None )
# OR... a python-style BaseException:
a = 16 / 0
class Task( java.lang.Runnable ):
def run( self ):
# NB the problem with all this stuff is that the Java stack trace shows
# a java.lang.Throwable occurring at the last line of this code block...
# print "lots of stuff first"
# print "lots 2"
# handle_exc()
# print "lots 3"
# print "lots of stuff after"
try:
print "lots of stuff first"
print "lots 2"
handle_exc()
print "lots 3"
print "lots of stuff after"
# NB do not catch both (Python) BaseException and java.lang.Throwable...
# except ( BaseException, java.lang.Throwable ), e:
# the above means that the line no. in handle_exc is not shown when a BaseException
# is thrown...
except java.lang.Throwable, t:
tb = sys.exc_info()[ 2 ]
sys.stderr.write( "java.lang.Throwable thrown at: %s\n" % tb.tb_lineno )
raise t
java.awt.EventQueue.invokeAndWait( Task() )
Run Code Online (Sandbox Code Playgroud)
在此之后,可能会想到在def run(self)和类似方法之前编写一个装饰器,这样你就不必每次都写出这个catch-the-Throwable try-except块...具体来说:
def throw_trap( function ):
def wrapper(*args, **kvargs):
try:
return function( *args, **kvargs )
except java.lang.Throwable, t:
tb = sys.exc_info()[ 2 ]
while( tb ):
sys.stderr.write( "thrown at: %s\n" % tb.tb_lineno )
tb = tb.tb_next
raise t
return wrapper
def handle_exc():
java.lang.String( None )
# a = 16 / 0
class Task( java.lang.Runnable ):
@throw_trap
def run( self ):
print "lots of stuff first"
print "lots 2"
handle_exc()
print "lots 3"
print "lots of stuff after"
java.awt.EventQueue.invokeAndWait( Task() )
Run Code Online (Sandbox Code Playgroud)