##// END OF EJS Templates
unregister crash handler on call...
MinRK -
Show More
@@ -1,181 +1,186 b''
1 1 # encoding: utf-8
2 2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian E. Granger
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
12 12 # Copyright (C) 2008-2010 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import os
23 23 import sys
24 24 from pprint import pformat
25 25
26 26 from IPython.core import ultratb
27 27 from IPython.utils.sysinfo import sys_info
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Code
31 31 #-----------------------------------------------------------------------------
32 32
33 33 # Template for the user message.
34 34 _default_message_template = """\
35 35 Oops, {app_name} crashed. We do our best to make it stable, but...
36 36
37 37 A crash report was automatically generated with the following information:
38 38 - A verbatim copy of the crash traceback.
39 39 - A copy of your input history during this session.
40 40 - Data on your current {app_name} configuration.
41 41
42 42 It was left in the file named:
43 43 \t'{crash_report_fname}'
44 44 If you can email this file to the developers, the information in it will help
45 45 them in understanding and correcting the problem.
46 46
47 47 You can mail it to: {contact_name} at {contact_email}
48 48 with the subject '{app_name} Crash Report'.
49 49
50 50 If you want to do it now, the following command will work (under Unix):
51 51 mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
52 52
53 53 To ensure accurate tracking of this issue, please file a report about it at:
54 54 {bug_tracker}
55 55 """
56 56
57 57
58 58 class CrashHandler(object):
59 59 """Customizable crash handlers for IPython applications.
60 60
61 61 Instances of this class provide a :meth:`__call__` method which can be
62 62 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
63 63
64 64 def __call__(self, etype, evalue, etb)
65 65 """
66 66
67 67 message_template = _default_message_template
68 68 section_sep = '\n\n'+'*'*75+'\n\n'
69 69
70 70 def __init__(self, app, contact_name=None, contact_email=None,
71 71 bug_tracker=None, show_crash_traceback=True, call_pdb=False):
72 72 """Create a new crash handler
73 73
74 74 Parameters
75 75 ----------
76 76 app : Application
77 77 A running :class:`Application` instance, which will be queried at
78 78 crash time for internal information.
79 79
80 80 contact_name : str
81 81 A string with the name of the person to contact.
82 82
83 83 contact_email : str
84 84 A string with the email address of the contact.
85 85
86 86 bug_tracker : str
87 87 A string with the URL for your project's bug tracker.
88 88
89 89 show_crash_traceback : bool
90 90 If false, don't print the crash traceback on stderr, only generate
91 91 the on-disk report
92 92
93 93 Non-argument instance attributes:
94 94
95 95 These instances contain some non-argument attributes which allow for
96 96 further customization of the crash handler's behavior. Please see the
97 97 source for further details.
98 98 """
99 99 self.crash_report_fname = "Crash_report_%s.txt" % app.name
100 100 self.app = app
101 101 self.call_pdb = call_pdb
102 102 #self.call_pdb = True # dbg
103 103 self.show_crash_traceback = show_crash_traceback
104 104 self.info = dict(app_name = app.name,
105 105 contact_name = contact_name,
106 106 contact_email = contact_email,
107 107 bug_tracker = bug_tracker,
108 108 crash_report_fname = self.crash_report_fname)
109 109
110 110
111 111 def __call__(self, etype, evalue, etb):
112 112 """Handle an exception, call for compatible with sys.excepthook"""
113
113
114 # do not allow the crash handler to be called twice without reinstalling it
115 # this prevents unlikely errors in the crash handling from entering an
116 # infinite loop.
117 sys.excepthook = sys.__excepthook__
118
114 119 # Report tracebacks shouldn't use color in general (safer for users)
115 120 color_scheme = 'NoColor'
116 121
117 122 # Use this ONLY for developer debugging (keep commented out for release)
118 123 #color_scheme = 'Linux' # dbg
119 124 try:
120 125 rptdir = self.app.ipython_dir
121 126 except:
122 127 rptdir = os.getcwdu()
123 128 if rptdir is None or not os.path.isdir(rptdir):
124 129 rptdir = os.getcwdu()
125 130 report_name = os.path.join(rptdir,self.crash_report_fname)
126 131 # write the report filename into the instance dict so it can get
127 132 # properly expanded out in the user message template
128 133 self.crash_report_fname = report_name
129 134 self.info['crash_report_fname'] = report_name
130 135 TBhandler = ultratb.VerboseTB(
131 136 color_scheme=color_scheme,
132 137 long_header=1,
133 138 call_pdb=self.call_pdb,
134 139 )
135 140 if self.call_pdb:
136 141 TBhandler(etype,evalue,etb)
137 142 return
138 143 else:
139 144 traceback = TBhandler.text(etype,evalue,etb,context=31)
140 145
141 146 # print traceback to screen
142 147 if self.show_crash_traceback:
143 148 print >> sys.stderr, traceback
144 149
145 150 # and generate a complete report on disk
146 151 try:
147 152 report = open(report_name,'w')
148 153 except:
149 154 print >> sys.stderr, 'Could not create crash report on disk.'
150 155 return
151 156
152 157 # Inform user on stderr of what happened
153 158 print >> sys.stderr, '\n'+'*'*70+'\n'
154 159 print >> sys.stderr, self.message_template.format(**self.info)
155 160
156 161 # Construct report on disk
157 162 report.write(self.make_report(traceback))
158 163 report.close()
159 164 raw_input("Hit <Enter> to quit this message (your terminal may close):")
160 165
161 166 def make_report(self,traceback):
162 167 """Return a string containing a crash report."""
163 168
164 169 sec_sep = self.section_sep
165 170
166 171 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
167 172 rpt_add = report.append
168 173 rpt_add(sys_info())
169 174
170 175 try:
171 176 config = pformat(self.app.config)
172 177 rpt_add(sec_sep)
173 178 rpt_add('Application name: %s\n\n' % self.app_name)
174 179 rpt_add('Current user configuration structure:\n\n')
175 180 rpt_add(config)
176 181 except:
177 182 pass
178 183 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
179 184
180 185 return ''.join(report)
181 186
General Comments 0
You need to be logged in to leave comments. Login now