execute.py
141 lines
| 4.3 KiB
| text/x-python
|
PythonLexer
Julia Evans
|
r17074 | """Module containing a preprocessor that removes the outputs from code cells""" | ||
# Copyright (c) IPython Development Team. | ||||
# Distributed under the terms of the Modified BSD License. | ||||
import os | ||||
Jessica B. Hamrick
|
r20747 | from textwrap import dedent | ||
Julia Evans
|
r17074 | |||
Julia Evans
|
r17087 | try: | ||
from queue import Empty # Py 3 | ||||
except ImportError: | ||||
from Queue import Empty # Py 2 | ||||
Jessica B. Hamrick
|
r20747 | from IPython.utils.traitlets import List, Unicode, Bool | ||
Julia Evans
|
r17074 | |||
MinRK
|
r18605 | from IPython.nbformat.v4 import output_from_msg | ||
Julia Evans
|
r17074 | from .base import Preprocessor | ||
MinRK
|
r17094 | from IPython.utils.traitlets import Integer | ||
Julia Evans
|
r17074 | |||
MinRK
|
r18605 | |||
Julia Evans
|
r17074 | class ExecutePreprocessor(Preprocessor): | ||
""" | ||||
Executes all the cells in a notebook | ||||
""" | ||||
MinRK
|
r17092 | |||
MinRK
|
r17094 | timeout = Integer(30, config=True, | ||
help="The time to wait (in seconds) for output from executions." | ||||
) | ||||
Jessica B. Hamrick
|
r20747 | |||
interrupt_on_timeout = Bool( | ||||
False, config=True, | ||||
help=dedent( | ||||
""" | ||||
If execution of a cell times out, interrupt the kernel and | ||||
continue executing other cells rather than throwing an error and | ||||
stopping. | ||||
""" | ||||
) | ||||
) | ||||
Jessica B. Hamrick
|
r20532 | |||
MinRK
|
r17092 | extra_arguments = List(Unicode) | ||
Julia Evans
|
r17079 | |||
Julia Evans
|
r17080 | def preprocess(self, nb, resources): | ||
Jessica B. Hamrick
|
r20648 | path = resources.get('metadata', {}).get('path', '') | ||
if path == '': | ||||
path = None | ||||
Jessica B. Hamrick
|
r20646 | |||
Jessica B. Hamrick
|
r20747 | from IPython.kernel.manager import start_new_kernel | ||
Thomas Kluyver
|
r17822 | kernel_name = nb.metadata.get('kernelspec', {}).get('name', 'python') | ||
MinRK
|
r18458 | self.log.info("Executing notebook with kernel: %s" % kernel_name) | ||
Jessica B. Hamrick
|
r20747 | self.km, self.kc = start_new_kernel( | ||
kernel_name=kernel_name, | ||||
extra_arguments=self.extra_arguments, | ||||
stderr=open(os.devnull, 'w'), | ||||
cwd=path) | ||||
self.kc.allow_stdin = False | ||||
try: | ||||
Thomas Kluyver
|
r17822 | nb, resources = super(ExecutePreprocessor, self).preprocess(nb, resources) | ||
Jessica B. Hamrick
|
r20747 | finally: | ||
self.kc.stop_channels() | ||||
self.km.shutdown_kernel(now=True) | ||||
Julia Evans
|
r17079 | return nb, resources | ||
Julia Evans
|
r17074 | def preprocess_cell(self, cell, resources, cell_index): | ||
""" | ||||
Apply a transformation on each code cell. See base.py for details. | ||||
""" | ||||
if cell.cell_type != 'code': | ||||
return cell, resources | ||||
try: | ||||
Thomas Kluyver
|
r19214 | outputs = self.run_cell(cell) | ||
Julia Evans
|
r17074 | except Exception as e: | ||
Julia Evans
|
r17078 | self.log.error("failed to run cell: " + repr(e)) | ||
MinRK
|
r18580 | self.log.error(str(cell.source)) | ||
MinRK
|
r17092 | raise | ||
Julia Evans
|
r17074 | cell.outputs = outputs | ||
return cell, resources | ||||
Thomas Kluyver
|
r19214 | def run_cell(self, cell): | ||
msg_id = self.kc.execute(cell.source) | ||||
MinRK
|
r18580 | self.log.debug("Executing cell:\n%s", cell.source) | ||
MinRK
|
r17092 | # wait for finish, with timeout | ||
while True: | ||||
try: | ||||
Thomas Kluyver
|
r19214 | msg = self.kc.shell_channel.get_msg(timeout=self.timeout) | ||
MinRK
|
r17092 | except Empty: | ||
self.log.error("Timeout waiting for execute reply") | ||||
Jessica B. Hamrick
|
r20747 | if self.interrupt_on_timeout: | ||
self.log.error("Interrupting kernel") | ||||
self.km.interrupt_kernel() | ||||
break | ||||
else: | ||||
raise | ||||
MinRK
|
r17092 | if msg['parent_header'].get('msg_id') == msg_id: | ||
break | ||||
else: | ||||
# not our reply | ||||
continue | ||||
Julia Evans
|
r17074 | outs = [] | ||
Julia Evans
|
r17077 | |||
Julia Evans
|
r17074 | while True: | ||
try: | ||||
Thomas Kluyver
|
r19214 | msg = self.kc.iopub_channel.get_msg(timeout=self.timeout) | ||
Julia Evans
|
r17074 | except Empty: | ||
MinRK
|
r17092 | self.log.warn("Timeout waiting for IOPub output") | ||
Julia Evans
|
r17074 | break | ||
MinRK
|
r17092 | if msg['parent_header'].get('msg_id') != msg_id: | ||
# not an output from our execution | ||||
continue | ||||
Jessica B. Hamrick
|
r17090 | |||
Julia Evans
|
r17074 | msg_type = msg['msg_type'] | ||
MinRK
|
r17092 | self.log.debug("output: %s", msg_type) | ||
Jessica B. Hamrick
|
r17090 | content = msg['content'] | ||
Jessica B. Hamrick
|
r17824 | |||
# set the prompt number for the input and the output | ||||
if 'execution_count' in content: | ||||
MinRK
|
r18587 | cell['execution_count'] = content['execution_count'] | ||
Jessica B. Hamrick
|
r17824 | |||
MinRK
|
r17092 | if msg_type == 'status': | ||
if content['execution_state'] == 'idle': | ||||
break | ||||
else: | ||||
continue | ||||
MinRK
|
r18582 | elif msg_type == 'execute_input': | ||
MinRK
|
r17092 | continue | ||
elif msg_type == 'clear_output': | ||||
outs = [] | ||||
continue | ||||
MinRK
|
r18580 | |||
MinRK
|
r18582 | try: | ||
out = output_from_msg(msg) | ||||
except ValueError: | ||||
Julia Evans
|
r17078 | self.log.error("unhandled iopub msg: " + msg_type) | ||
MinRK
|
r18582 | else: | ||
outs.append(out) | ||||
Julia Evans
|
r17077 | |||
Julia Evans
|
r17074 | return outs | ||