##// END OF EJS Templates
Handle comm messages in execute preprocessor
Jessica B. Hamrick -
Show More
@@ -1,141 +1,143 b''
1 1 """Module containing a preprocessor that removes the outputs from code cells"""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 import os
7 7 from textwrap import dedent
8 8
9 9 try:
10 10 from queue import Empty # Py 3
11 11 except ImportError:
12 12 from Queue import Empty # Py 2
13 13
14 14 from IPython.utils.traitlets import List, Unicode, Bool
15 15
16 16 from IPython.nbformat.v4 import output_from_msg
17 17 from .base import Preprocessor
18 18 from IPython.utils.traitlets import Integer
19 19
20 20
21 21 class ExecutePreprocessor(Preprocessor):
22 22 """
23 23 Executes all the cells in a notebook
24 24 """
25 25
26 26 timeout = Integer(30, config=True,
27 27 help="The time to wait (in seconds) for output from executions."
28 28 )
29 29
30 30 interrupt_on_timeout = Bool(
31 31 False, config=True,
32 32 help=dedent(
33 33 """
34 34 If execution of a cell times out, interrupt the kernel and
35 35 continue executing other cells rather than throwing an error and
36 36 stopping.
37 37 """
38 38 )
39 39 )
40 40
41 41 extra_arguments = List(Unicode)
42 42
43 43 def preprocess(self, nb, resources):
44 44 path = resources.get('metadata', {}).get('path', '')
45 45 if path == '':
46 46 path = None
47 47
48 48 from IPython.kernel.manager import start_new_kernel
49 49 kernel_name = nb.metadata.get('kernelspec', {}).get('name', 'python')
50 50 self.log.info("Executing notebook with kernel: %s" % kernel_name)
51 51 self.km, self.kc = start_new_kernel(
52 52 kernel_name=kernel_name,
53 53 extra_arguments=self.extra_arguments,
54 54 stderr=open(os.devnull, 'w'),
55 55 cwd=path)
56 56 self.kc.allow_stdin = False
57 57
58 58 try:
59 59 nb, resources = super(ExecutePreprocessor, self).preprocess(nb, resources)
60 60 finally:
61 61 self.kc.stop_channels()
62 62 self.km.shutdown_kernel(now=True)
63 63
64 64 return nb, resources
65 65
66 66 def preprocess_cell(self, cell, resources, cell_index):
67 67 """
68 68 Apply a transformation on each code cell. See base.py for details.
69 69 """
70 70 if cell.cell_type != 'code':
71 71 return cell, resources
72 72 try:
73 73 outputs = self.run_cell(cell)
74 74 except Exception as e:
75 75 self.log.error("failed to run cell: " + repr(e))
76 76 self.log.error(str(cell.source))
77 77 raise
78 78 cell.outputs = outputs
79 79 return cell, resources
80 80
81 81 def run_cell(self, cell):
82 82 msg_id = self.kc.execute(cell.source)
83 83 self.log.debug("Executing cell:\n%s", cell.source)
84 84 # wait for finish, with timeout
85 85 while True:
86 86 try:
87 87 msg = self.kc.shell_channel.get_msg(timeout=self.timeout)
88 88 except Empty:
89 89 self.log.error("Timeout waiting for execute reply")
90 90 if self.interrupt_on_timeout:
91 91 self.log.error("Interrupting kernel")
92 92 self.km.interrupt_kernel()
93 93 break
94 94 else:
95 95 raise
96 96
97 97 if msg['parent_header'].get('msg_id') == msg_id:
98 98 break
99 99 else:
100 100 # not our reply
101 101 continue
102 102
103 103 outs = []
104 104
105 105 while True:
106 106 try:
107 107 msg = self.kc.iopub_channel.get_msg(timeout=self.timeout)
108 108 except Empty:
109 109 self.log.warn("Timeout waiting for IOPub output")
110 110 break
111 111 if msg['parent_header'].get('msg_id') != msg_id:
112 112 # not an output from our execution
113 113 continue
114 114
115 115 msg_type = msg['msg_type']
116 116 self.log.debug("output: %s", msg_type)
117 117 content = msg['content']
118 118
119 119 # set the prompt number for the input and the output
120 120 if 'execution_count' in content:
121 121 cell['execution_count'] = content['execution_count']
122 122
123 123 if msg_type == 'status':
124 124 if content['execution_state'] == 'idle':
125 125 break
126 126 else:
127 127 continue
128 128 elif msg_type == 'execute_input':
129 129 continue
130 130 elif msg_type == 'clear_output':
131 131 outs = []
132 132 continue
133 elif msg_type.startswith('comm'):
134 continue
133 135
134 136 try:
135 137 out = output_from_msg(msg)
136 138 except ValueError:
137 139 self.log.error("unhandled iopub msg: " + msg_type)
138 140 else:
139 141 outs.append(out)
140 142
141 143 return outs
General Comments 0
You need to be logged in to leave comments. Login now