如何在python中捕获异常并获取对异常的引用,而不知道类型?

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异常


mik*_*ent 5

只是对任何感兴趣的人...我花了一些时间测试东西,因为我想找出如何获得正确的堆栈跟踪,无论是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)