runapp.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # Copyright (c) Jupyter Development Team.
  2. # Distributed under the terms of the Modified BSD License.
  3. from __future__ import print_function
  4. import logging
  5. import signal
  6. import time
  7. import sys
  8. from traitlets.config import catch_config_error
  9. from traitlets import (
  10. Instance, Dict, Unicode, Bool, List, CUnicode, Any, Float
  11. )
  12. from jupyter_core.application import (
  13. JupyterApp, base_flags, base_aliases
  14. )
  15. from . import __version__
  16. from .consoleapp import JupyterConsoleApp, app_aliases, app_flags
  17. try:
  18. import queue
  19. except ImportError:
  20. import Queue as queue
  21. OUTPUT_TIMEOUT = 10
  22. # copy flags from mixin:
  23. flags = dict(base_flags)
  24. # start with mixin frontend flags:
  25. frontend_flags = dict(app_flags)
  26. # update full dict with frontend flags:
  27. flags.update(frontend_flags)
  28. # copy flags from mixin
  29. aliases = dict(base_aliases)
  30. # start with mixin frontend flags
  31. frontend_aliases = dict(app_aliases)
  32. # load updated frontend flags into full dict
  33. aliases.update(frontend_aliases)
  34. # get flags&aliases into sets, and remove a couple that
  35. # shouldn't be scrubbed from backend flags:
  36. frontend_aliases = set(frontend_aliases.keys())
  37. frontend_flags = set(frontend_flags.keys())
  38. class RunApp(JupyterApp, JupyterConsoleApp):
  39. version = __version__
  40. name = "jupyter run"
  41. description = """Run Jupyter kernel code."""
  42. flags = Dict(flags)
  43. aliases = Dict(aliases)
  44. frontend_aliases = Any(frontend_aliases)
  45. frontend_flags = Any(frontend_flags)
  46. kernel_timeout = Float(60, config=True,
  47. help="""Timeout for giving up on a kernel (in seconds).
  48. On first connect and restart, the console tests whether the
  49. kernel is running and responsive by sending kernel_info_requests.
  50. This sets the timeout in seconds for how long the kernel can take
  51. before being presumed dead.
  52. """
  53. )
  54. def parse_command_line(self, argv=None):
  55. super(RunApp, self).parse_command_line(argv)
  56. self.build_kernel_argv(self.extra_args)
  57. self.filenames_to_run = self.extra_args[:]
  58. @catch_config_error
  59. def initialize(self, argv=None):
  60. self.log.debug("jupyter run: initialize...")
  61. super(RunApp, self).initialize(argv)
  62. JupyterConsoleApp.initialize(self)
  63. signal.signal(signal.SIGINT, self.handle_sigint)
  64. self.init_kernel_info()
  65. def handle_sigint(self, *args):
  66. if self.kernel_manager:
  67. self.kernel_manager.interrupt_kernel()
  68. else:
  69. print("", file=sys.stderr)
  70. error("Cannot interrupt kernels we didn't start.\n")
  71. def init_kernel_info(self):
  72. """Wait for a kernel to be ready, and store kernel info"""
  73. timeout = self.kernel_timeout
  74. tic = time.time()
  75. self.kernel_client.hb_channel.unpause()
  76. msg_id = self.kernel_client.kernel_info()
  77. while True:
  78. try:
  79. reply = self.kernel_client.get_shell_msg(timeout=1)
  80. except queue.Empty:
  81. if (time.time() - tic) > timeout:
  82. raise RuntimeError("Kernel didn't respond to kernel_info_request")
  83. else:
  84. if reply['parent_header'].get('msg_id') == msg_id:
  85. self.kernel_info = reply['content']
  86. return
  87. def start(self):
  88. self.log.debug("jupyter run: starting...")
  89. super(RunApp, self).start()
  90. if self.filenames_to_run:
  91. for filename in self.filenames_to_run:
  92. self.log.debug("jupyter run: executing `%s`" % filename)
  93. with open(filename) as fp:
  94. code = fp.read()
  95. reply = self.kernel_client.execute_interactive(code, timeout=OUTPUT_TIMEOUT)
  96. return_code = 0 if reply['content']['status'] == 'ok' else 1
  97. if return_code:
  98. raise Exception("jupyter-run error running '%s'" % filename)
  99. else:
  100. code = sys.stdin.read()
  101. reply = self.kernel_client.execute_interactive(code, timeout=OUTPUT_TIMEOUT)
  102. return_code = 0 if reply['content']['status'] == 'ok' else 1
  103. if return_code:
  104. raise Exception("jupyter-run error running 'stdin'")
  105. main = launch_new_instance = RunApp.launch_instance
  106. if __name__ == '__main__':
  107. main()