| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- """An application to launch a kernel by name in a local subprocess."""
- import os
- import signal
- import typing as t
- import uuid
- from jupyter_core.application import JupyterApp, base_flags
- from tornado.ioloop import IOLoop
- from traitlets import Unicode
- from . import __version__
- from .kernelspec import NATIVE_KERNEL_NAME, KernelSpecManager
- from .manager import KernelManager
- class KernelApp(JupyterApp):
- """Launch a kernel by name in a local subprocess."""
- version = __version__
- description = "Run a kernel locally in a subprocess"
- classes = [KernelManager, KernelSpecManager]
- aliases = {
- "kernel": "KernelApp.kernel_name",
- "ip": "KernelManager.ip",
- }
- flags = {"debug": base_flags["debug"]}
- kernel_name = Unicode(NATIVE_KERNEL_NAME, help="The name of a kernel type to start").tag(
- config=True
- )
- def initialize(self, argv: t.Union[str, t.Sequence[str], None] = None) -> None:
- """Initialize the application."""
- super().initialize(argv)
- cf_basename = "kernel-%s.json" % uuid.uuid4()
- self.config.setdefault("KernelManager", {}).setdefault(
- "connection_file", os.path.join(self.runtime_dir, cf_basename)
- )
- self.km = KernelManager(kernel_name=self.kernel_name, config=self.config)
- self.loop = IOLoop.current()
- self.loop.add_callback(self._record_started)
- def setup_signals(self) -> None:
- """Shutdown on SIGTERM or SIGINT (Ctrl-C)"""
- if os.name == "nt":
- return
- def shutdown_handler(signo: int, frame: t.Any) -> None:
- self.loop.add_callback_from_signal(self.shutdown, signo)
- for sig in [signal.SIGTERM, signal.SIGINT]:
- signal.signal(sig, shutdown_handler)
- def shutdown(self, signo: int) -> None:
- """Shut down the application."""
- self.log.info("Shutting down on signal %d", signo)
- self.km.shutdown_kernel()
- self.loop.stop()
- def log_connection_info(self) -> None:
- """Log the connection info for the kernel."""
- cf = self.km.connection_file
- self.log.info("Connection file: %s", cf)
- self.log.info("To connect a client: --existing %s", os.path.basename(cf))
- def _record_started(self) -> None:
- """For tests, create a file to indicate that we've started
- Do not rely on this except in our own tests!
- """
- fn = os.environ.get("JUPYTER_CLIENT_TEST_RECORD_STARTUP_PRIVATE")
- if fn is not None:
- with open(fn, "wb"):
- pass
- def start(self) -> None:
- """Start the application."""
- self.log.info("Starting kernel %r", self.kernel_name)
- try:
- self.km.start_kernel()
- self.log_connection_info()
- self.setup_signals()
- self.loop.start()
- finally:
- self.km.cleanup_resources()
- main = KernelApp.launch_instance
|