##// END OF EJS Templates
Merge pull request #2871 from minrk/shortexc...
Brian E. Granger -
r9725:c2bc10dd merge
parent child Browse files
Show More
@@ -232,6 +232,8 b' class TaskRejectError(KernelError):'
232
232
233 class CompositeError(RemoteError):
233 class CompositeError(RemoteError):
234 """Error for representing possibly multiple errors on engines"""
234 """Error for representing possibly multiple errors on engines"""
235 tb_limit = 4 # limit on how many tracebacks to draw
236
235 def __init__(self, message, elist):
237 def __init__(self, message, elist):
236 Exception.__init__(self, *(message, elist))
238 Exception.__init__(self, *(message, elist))
237 # Don't use pack_exception because it will conflict with the .message
239 # Don't use pack_exception because it will conflict with the .message
@@ -256,22 +258,28 b' class CompositeError(RemoteError):'
256
258
257 def __str__(self):
259 def __str__(self):
258 s = str(self.msg)
260 s = str(self.msg)
259 for en, ev, etb, ei in self.elist:
261 for en, ev, etb, ei in self.elist[:self.tb_limit]:
260 engine_str = self._get_engine_str(ei)
262 engine_str = self._get_engine_str(ei)
261 s = s + '\n' + engine_str + en + ': ' + str(ev)
263 s = s + '\n' + engine_str + en + ': ' + str(ev)
264 if len(self.elist) > self.tb_limit:
265 s = s + '\n.... %i more exceptions ...' % (len(self.elist) - self.tb_limit)
262 return s
266 return s
263
267
264 def __repr__(self):
268 def __repr__(self):
265 return "CompositeError(%i)"%len(self.elist)
269 return "CompositeError(%i)" % len(self.elist)
266
270
267 def render_traceback(self, excid=None):
271 def render_traceback(self, excid=None):
268 """render one or all of my tracebacks to a list of lines"""
272 """render one or all of my tracebacks to a list of lines"""
269 lines = []
273 lines = []
270 if excid is None:
274 if excid is None:
271 for (en,ev,etb,ei) in self.elist:
275 for (en,ev,etb,ei) in self.elist[:self.tb_limit]:
272 lines.append(self._get_engine_str(ei))
276 lines.append(self._get_engine_str(ei))
273 lines.extend((etb or 'No traceback available').splitlines())
277 lines.extend((etb or 'No traceback available').splitlines())
274 lines.append('')
278 lines.append('')
279 if len(self.elist) > self.tb_limit:
280 lines.append(
281 '... %i more exceptions ...' % (len(self.elist) - self.tb_limit)
282 )
275 else:
283 else:
276 try:
284 try:
277 en,ev,etb,ei = self.elist[excid]
285 en,ev,etb,ei = self.elist[excid]
@@ -622,6 +622,33 b' class TestView(ClusterTestCase, ParametricTestCase):'
622 self.assertEqual(io.stdout.count('by zero'), len(view), io.stdout)
622 self.assertEqual(io.stdout.count('by zero'), len(view), io.stdout)
623 self.assertEqual(io.stdout.count(':execute'), len(view), io.stdout)
623 self.assertEqual(io.stdout.count(':execute'), len(view), io.stdout)
624
624
625 def test_compositeerror_truncate(self):
626 """Truncate CompositeErrors with many exceptions"""
627 view = self.client[:]
628 msg_ids = []
629 for i in range(10):
630 ar = view.execute("1/0")
631 msg_ids.extend(ar.msg_ids)
632
633 ar = self.client.get_result(msg_ids)
634 try:
635 ar.get()
636 except error.CompositeError as e:
637 pass
638 else:
639 self.fail("Should have raised CompositeError")
640
641 lines = e.render_traceback()
642 with capture_output() as io:
643 e.print_traceback()
644
645 self.assertTrue("more exceptions" in lines[-1])
646 count = e.tb_limit
647
648 self.assertEqual(io.stdout.count('ZeroDivisionError'), 2 * count, io.stdout)
649 self.assertEqual(io.stdout.count('by zero'), count, io.stdout)
650 self.assertEqual(io.stdout.count(':execute'), count, io.stdout)
651
625 @dec.skipif_not_matplotlib
652 @dec.skipif_not_matplotlib
626 def test_magic_pylab(self):
653 def test_magic_pylab(self):
627 """%pylab works on engines"""
654 """%pylab works on engines"""
@@ -560,25 +560,25 b' more other types of exceptions. Here is how it works:'
560 In [79]: dview.execute("1/0")
560 In [79]: dview.execute("1/0")
561 [0:execute]:
561 [0:execute]:
562 ---------------------------------------------------------------------------
562 ---------------------------------------------------------------------------
563 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
563 ZeroDivisionError Traceback (most recent call last)
564 ----> 1 1/0
564 ----> 1 1/0
565 ZeroDivisionError: integer division or modulo by zero
565 ZeroDivisionError: integer division or modulo by zero
566
566
567 [1:execute]:
567 [1:execute]:
568 ---------------------------------------------------------------------------
568 ---------------------------------------------------------------------------
569 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
569 ZeroDivisionError Traceback (most recent call last)
570 ----> 1 1/0
570 ----> 1 1/0
571 ZeroDivisionError: integer division or modulo by zero
571 ZeroDivisionError: integer division or modulo by zero
572
572
573 [2:execute]:
573 [2:execute]:
574 ---------------------------------------------------------------------------
574 ---------------------------------------------------------------------------
575 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
575 ZeroDivisionError Traceback (most recent call last)
576 ----> 1 1/0
576 ----> 1 1/0
577 ZeroDivisionError: integer division or modulo by zero
577 ZeroDivisionError: integer division or modulo by zero
578
578
579 [3:execute]:
579 [3:execute]:
580 ---------------------------------------------------------------------------
580 ---------------------------------------------------------------------------
581 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
581 ZeroDivisionError Traceback (most recent call last)
582 ----> 1 1/0
582 ----> 1 1/0
583 ZeroDivisionError: integer division or modulo by zero
583 ZeroDivisionError: integer division or modulo by zero
584
584
@@ -595,7 +595,7 b' If you want, you can even raise one of these original exceptions:'
595 ....:
595 ....:
596 ....:
596 ....:
597 ---------------------------------------------------------------------------
597 ---------------------------------------------------------------------------
598 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
598 ZeroDivisionError Traceback (most recent call last)
599 ----> 1 1/0
599 ----> 1 1/0
600 ZeroDivisionError: integer division or modulo by zero
600 ZeroDivisionError: integer division or modulo by zero
601
601
@@ -608,25 +608,25 b' instance:'
608 In [81]: dview.execute('1/0')
608 In [81]: dview.execute('1/0')
609 [0:execute]:
609 [0:execute]:
610 ---------------------------------------------------------------------------
610 ---------------------------------------------------------------------------
611 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
611 ZeroDivisionError Traceback (most recent call last)
612 ----> 1 1/0
612 ----> 1 1/0
613 ZeroDivisionError: integer division or modulo by zero
613 ZeroDivisionError: integer division or modulo by zero
614
614
615 [1:execute]:
615 [1:execute]:
616 ---------------------------------------------------------------------------
616 ---------------------------------------------------------------------------
617 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
617 ZeroDivisionError Traceback (most recent call last)
618 ----> 1 1/0
618 ----> 1 1/0
619 ZeroDivisionError: integer division or modulo by zero
619 ZeroDivisionError: integer division or modulo by zero
620
620
621 [2:execute]:
621 [2:execute]:
622 ---------------------------------------------------------------------------
622 ---------------------------------------------------------------------------
623 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
623 ZeroDivisionError Traceback (most recent call last)
624 ----> 1 1/0
624 ----> 1 1/0
625 ZeroDivisionError: integer division or modulo by zero
625 ZeroDivisionError: integer division or modulo by zero
626
626
627 [3:execute]:
627 [3:execute]:
628 ---------------------------------------------------------------------------
628 ---------------------------------------------------------------------------
629 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
629 ZeroDivisionError Traceback (most recent call last)
630 ----> 1 1/0
630 ----> 1 1/0
631 ZeroDivisionError: integer division or modulo by zero
631 ZeroDivisionError: integer division or modulo by zero
632
632
@@ -654,11 +654,31 b' instance:'
654 ipdb> e.print_traceback(1)
654 ipdb> e.print_traceback(1)
655 [1:execute]:
655 [1:execute]:
656 ---------------------------------------------------------------------------
656 ---------------------------------------------------------------------------
657 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
657 ZeroDivisionError Traceback (most recent call last)
658 ----> 1 1/0
658 ----> 1 1/0
659 ZeroDivisionError: integer division or modulo by zero
659 ZeroDivisionError: integer division or modulo by zero
660
660
661
661
662 Since you might have 100 engines, you probably don't want to see 100 tracebacks
663 for a simple NameError because of a typo.
664 For this reason, CompositeError truncates the list of exceptions it will print
665 to :attr:`CompositeError.tb_limit` (default is five).
666 You can change this limit to suit your needs with:
667
668 .. sourcecode:: ipython
669
670 In [20]: from IPython.parallel import CompositeError
671 In [21]: CompositeError.tb_limit = 1
672 In [22]: %px a=b
673 [0:execute]:
674 ---------------------------------------------------------------------------
675 NameError Traceback (most recent call last)
676 ----> 1 a=b
677 NameError: name 'b' is not defined
678
679 ... 3 more exceptions ...
680
681
662 All of this same error handling magic even works in non-blocking mode:
682 All of this same error handling magic even works in non-blocking mode:
663
683
664 .. sourcecode:: ipython
684 .. sourcecode:: ipython
@@ -670,25 +690,8 b' All of this same error handling magic even works in non-blocking mode:'
670 In [85]: ar.get()
690 In [85]: ar.get()
671 [0:execute]:
691 [0:execute]:
672 ---------------------------------------------------------------------------
692 ---------------------------------------------------------------------------
673 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
693 ZeroDivisionError Traceback (most recent call last)
674 ----> 1 1/0
675 ZeroDivisionError: integer division or modulo by zero
676
677 [1:execute]:
678 ---------------------------------------------------------------------------
679 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
680 ----> 1 1/0
694 ----> 1 1/0
681 ZeroDivisionError: integer division or modulo by zero
695 ZeroDivisionError: integer division or modulo by zero
682
696
683 [2:execute]:
697 ... 3 more exceptions ...
684 ---------------------------------------------------------------------------
685 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
686 ----> 1 1/0
687 ZeroDivisionError: integer division or modulo by zero
688
689 [3:execute]:
690 ---------------------------------------------------------------------------
691 ZeroDivisionError Traceback (most recent call last)<ipython-input-1-05c9758a9c21> in <module>()
692 ----> 1 1/0
693 ZeroDivisionError: integer division or modulo by zero
694
General Comments 0
You need to be logged in to leave comments. Login now