[docs]classComputationError(Exception):"""Wrapper to print intelligible exception information for :meth:`.Computer.get`. In order to aid in debugging, this helper: - Omits the parts of the stack trace that are internal to :mod:`dask`, and - Gives the key in the :attr:`.Computer.graph` and the computation/task that caused the exception. """def__init__(self,exc):self._exc=excdef__str__(self):"""String representation. Most exception handling (Python, IPython, Jupyter) will print the traceback that led to `self` (i.e. the call to :meth:`.Computer.get`), followed by the string returned by this method. """try:returnself._format()exceptExceptionasformat_exc:# Something went wrong during _format()log.error(f"Exception raised while formatting {self._exc}:\n"+repr(format_exc))# Fall back to printing the underlying exceptionreturnstr(self._exc)def_format(self):key,task,frames=process_dask_tb(self._exc)# Assemble the exception printoutreturn"".join(chain(# Computer information for debugging[f"computing {key} using:\n\n"ifkeyelse"",f"{task}\n\n"iftaskelse"","Use Computer.describe(...) to trace the computation.\n\n","Computation traceback:\n",],# Traceback; omitting a few dask internal calls below execute_taskformat_list(frames),# Type and message of the original exceptionformat_exception_only(self._exc.__class__,self._exc),))
[docs]classKeyExistsError(KeyError):"""Raised by :meth:`.Computer.add` when the target key exists."""def__str__(self):returnf"key {repr(self.args[0])} already exists"
[docs]classMissingKeyError(KeyError):"""Raised by :meth:`.Computer.add` when a required input key is missing."""def__str__(self):returnf"required keys {repr(self.args)} not defined"
defprocess_dask_tb(exc):"""Process *exc* arising from :meth:`.Computer.get`. Returns a tuple with 3 elements: - The key of the computation. - The info key of the computation. - A list of traceback.FrameSummary objects, without locals, for *only* frames that are not internal to dask. """key=task=None# Info about the computation that triggered *exc*frames=[]# Frames for an abbreviated stacktracetry:# Get a traceback with captured localstbe=TracebackException.from_exception(exc,capture_locals=True)exceptException:# Some exception occurred when capturing locals; proceed withouttbe=TracebackException.from_exception(exc)# Iterate over frames from the base of the stack# Initial frames are internal to daskdask_internal=Trueforframeintbe.stack:ifframe.name=="execute_task":# Current frame is the dask internal call to execute a tasktry:# Retrieve information about the key/task that triggered the# exception. These are not the raw values of variables, but# their string repr().key=frame.locals["key"]task=frame.locals["task"]except(TypeError,KeyError):# pragma: no cover# No locals, or 'key' or 'task' not presentpass# Subsequent frames are related to the exceptiondask_internal=Falseifnotdask_internal:# Don't display the locals when printing the tracebackframe.locals=None# Store the frame for printing the tracebackframes.append(frame)# Omit a few dask internal calls below execute_taskreturnkey,task,frames[3:]