By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,222 Members | 2,354 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,222 IT Pros & Developers. It's quick & easy.

Storing tracebacks

P: n/a
I'm reading the docs on sys.exc_info() but I can't tell for sure
whether I'm using it safely to get a snapshot of an exception and
reraise it later. The use case is a class which acts like a deferred
callable, a callable that will be called at some point in the future
(possibly in a different thread) and whose result or raised exception
is to be stored as an attribute. This will be available by calling the
result() method, which returns the original result or reraises the
exception:

class JobRequest(object):

def __init__(self, *args, **kwds):
self.args = args
self.kwds = kwds
self._exc_info = None

def __call__(self):
raise NotImplementedError('Abstract method')

def process(self):
try:
self._result = self(*self.args, **self.kwds)
except:
self._exc_info = sys.exc_info()
else:
self._exc_info = None

def result(self):
if self._exc_info is not None:
type,exception,traceback = self._exc_info
raise type,exception,traceback
try: return self._result
except AttributeError:
raise UnprocessedRequestError()

class UnprocessedRequestError(RuntimeError):
pass
So far it seems it works as expected but I'd like to know if this is
error-prone and why.

George

May 29 '07 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On May 28, 10:46 pm, George Sakkis <george.sak...@gmail.comwrote:
I'm reading the docs on sys.exc_info() but I can't tell for sure
whether I'm using it safely to get a snapshot of an exception and
reraise it later. The use case is a class which acts like a deferred
callable, a callable that will be called at some point in the future
(possibly in a different thread) and whose result or raised exception
is to be stored as an attribute. This will be available by calling the
result() method, which returns the original result or reraises the
exception:

class JobRequest(object):

def __init__(self, *args, **kwds):
self.args = args
self.kwds = kwds
self._exc_info = None

def __call__(self):
raise NotImplementedError('Abstract method')

def process(self):
try:
self._result = self(*self.args, **self.kwds)
except:
self._exc_info = sys.exc_info()
else:
self._exc_info = None

def result(self):
if self._exc_info is not None:
type,exception,traceback = self._exc_info
raise type,exception,traceback
try: return self._result
except AttributeError:
raise UnprocessedRequestError()

class UnprocessedRequestError(RuntimeError):
pass

So far it seems it works as expected but I'd like to know if this is
error-prone and why.

George
I don't know enough about this method of getting tracebacks, but why
wouldn't the traceback module work for you? It sounds like it uses the
sys.exc_info() method you refer to.

http://python.active-venture.com/lib...traceback.html

Mike

May 29 '07 #2

P: n/a
On May 29, 9:46 am, kyoso...@gmail.com wrote:
On May 28, 10:46 pm, George Sakkis <george.sak...@gmail.comwrote:
I'm reading the docs on sys.exc_info() but I can't tell for sure
whether I'm using it safely to get a snapshot of an exception and
reraise it later. The use case is a class which acts like a deferred
callable, a callable that will be called at some point in the future
(possibly in a different thread) and whose result or raised exception
is to be stored as an attribute. This will be available by calling the
result() method, which returns the original result or reraises the
exception:
class JobRequest(object):
def __init__(self, *args, **kwds):
self.args = args
self.kwds = kwds
self._exc_info = None
def __call__(self):
raise NotImplementedError('Abstract method')
def process(self):
try:
self._result = self(*self.args, **self.kwds)
except:
self._exc_info = sys.exc_info()
else:
self._exc_info = None
def result(self):
if self._exc_info is not None:
type,exception,traceback = self._exc_info
raise type,exception,traceback
try: return self._result
except AttributeError:
raise UnprocessedRequestError()
class UnprocessedRequestError(RuntimeError):
pass
So far it seems it works as expected but I'd like to know if this is
error-prone and why.
George

I don't know enough about this method of getting tracebacks, but why
wouldn't the traceback module work for you? It sounds like it uses the
sys.exc_info() method you refer to.

http://python.active-venture.com/lib...traceback.html
The traceback module is handy if you want a text representation of the
traceback, not the actual traceback. The reason I want to store the
actual traceback is to make the exception transparent to the user,
i.e. not be able to tell whether the exception was thrown in the
current stack frame or in another thread or even process.
Unfortunately tracebacks are not pickleable, otherwise I could just
pickle them in process() and unpickle them in result().

George

May 29 '07 #3

P: n/a
En Tue, 29 May 2007 13:51:09 -0300, George Sakkis
<ge***********@gmail.comescribió:
The traceback module is handy if you want a text representation of the
traceback, not the actual traceback. The reason I want to store the
actual traceback is to make the exception transparent to the user,
i.e. not be able to tell whether the exception was thrown in the
current stack frame or in another thread or even process.
Unfortunately tracebacks are not pickleable, otherwise I could just
pickle them in process() and unpickle them in result().
A traceback contains a linked list of frames, each with its own globals
and locals and lot of context info.
I'm not sure that moving a traceback across processes has any sense; a
textual representation should be enough, as t.b. are usually a debugging
aid and not supposed to reach the final user.

--
Gabriel Genellina

May 29 '07 #4

P: n/a
On May 29, 1:21 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
En Tue, 29 May 2007 13:51:09 -0300, George Sakkis
<george.sak...@gmail.comescribió:
The traceback module is handy if you want a text representation of the
traceback, not the actual traceback. The reason I want to store the
actual traceback is to make the exception transparent to the user,
i.e. not be able to tell whether the exception was thrown in the
current stack frame or in another thread or even process.
Unfortunately tracebacks are not pickleable, otherwise I could just
pickle them in process() and unpickle them in result().

A traceback contains a linked list of frames, each with its own globals
and locals and lot of context info.
I'm not sure that moving a traceback across processes has any sense; a
textual representation should be enough, as t.b. are usually a debugging
aid and not supposed to reach the final user.
The final user in this case is another programmer that uses a library,
not some random guy using an application, so he certainly would be
interested in seeing the traceback. I agree that the traceback is
useful for debugging and the text representation would be enough if,
for example, it was stored as an attribute in the Exception object and
then used automatically by the runtime system (instead of calling
sys.exc_info()). Of course nobody stops me from sticking
traceback.format_tb() as an attribute in the Exception object and then
have the client access it explicitly, something like:

try: r = job.result()
except Exception, ex:
print ex.traceback

The problem with this is that it's not transparent any more. The
client must know that the originally raised object has been modified
(or wrapped), sys.exc_info() doesn't work as expected, etc. It's not a
show stopper by any means, but it would be convenient if there was a
standardized optional "traceback" attribute that the runtime looks for
and treats as the 3rd item of sys.exc_info() (otherwise it falls back
to the current behavior). Would this be a reasonable feature request ?

George

May 29 '07 #5

P: n/a
En Tue, 29 May 2007 15:13:33 -0300, George Sakkis
<ge***********@gmail.comescribió:
On May 29, 1:21 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
>A traceback contains a linked list of frames, each with its own globals
and locals and lot of context info.
I'm not sure that moving a traceback across processes has any sense; a
textual representation should be enough, as t.b. are usually a debugging
aid and not supposed to reach the final user.

The final user in this case is another programmer that uses a library,
not some random guy using an application, so he certainly would be
interested in seeing the traceback. I agree that the traceback is
useful for debugging and the text representation would be enough if,
for example, it was stored as an attribute in the Exception object and
then used automatically by the runtime system (instead of calling
sys.exc_info()). Of course nobody stops me from sticking
traceback.format_tb() as an attribute in the Exception object and then
have the client access it explicitly, something like:

try: r = job.result()
except Exception, ex:
print ex.traceback

The problem with this is that it's not transparent any more. The
client must know that the originally raised object has been modified
(or wrapped), sys.exc_info() doesn't work as expected, etc. It's not a
show stopper by any means, but it would be convenient if there was a
standardized optional "traceback" attribute that the runtime looks for
and treats as the 3rd item of sys.exc_info() (otherwise it falls back
to the current behavior). Would this be a reasonable feature request ?
Already requested - see PEP 344 and 3110 for changes on exception handling
and tracebacks (in Python 3.0 at least; I'm unsure of the PEP344 status on
the 2.X series)

--
Gabriel Genellina

May 29 '07 #6

This discussion thread is closed

Replies have been disabled for this discussion.