Show More
@@ -90,8 +90,7 b' def validate_string_dict(dct):' | |||||
90 | #----------------------------------------------------------------------------- |
|
90 | #----------------------------------------------------------------------------- | |
91 |
|
91 | |||
92 | class ZMQSocketChannel(Thread): |
|
92 | class ZMQSocketChannel(Thread): | |
93 | """The base class for the channels that use ZMQ sockets. |
|
93 | """The base class for the channels that use ZMQ sockets.""" | |
94 | """ |
|
|||
95 | context = None |
|
94 | context = None | |
96 | session = None |
|
95 | session = None | |
97 | socket = None |
|
96 | socket = None | |
@@ -101,7 +100,7 b' class ZMQSocketChannel(Thread):' | |||||
101 | _exiting = False |
|
100 | _exiting = False | |
102 |
|
101 | |||
103 | def __init__(self, context, session, address): |
|
102 | def __init__(self, context, session, address): | |
104 | """Create a channel |
|
103 | """Create a channel. | |
105 |
|
104 | |||
106 | Parameters |
|
105 | Parameters | |
107 | ---------- |
|
106 | ---------- | |
@@ -147,7 +146,7 b' class ZMQSocketChannel(Thread):' | |||||
147 | break |
|
146 | break | |
148 |
|
147 | |||
149 | def stop(self): |
|
148 | def stop(self): | |
150 |
"""Stop the channel's |
|
149 | """Stop the channel's event loop and join its thread. | |
151 |
|
150 | |||
152 | This calls :method:`Thread.join` and returns when the thread |
|
151 | This calls :method:`Thread.join` and returns when the thread | |
153 | terminates. :class:`RuntimeError` will be raised if |
|
152 | terminates. :class:`RuntimeError` will be raised if | |
@@ -157,7 +156,9 b' class ZMQSocketChannel(Thread):' | |||||
157 |
|
156 | |||
158 | @property |
|
157 | @property | |
159 | def address(self): |
|
158 | def address(self): | |
160 |
"""Get the channel's address as a zmq url string |
|
159 | """Get the channel's address as a zmq url string. | |
|
160 | ||||
|
161 | These URLS have the form: 'tcp://127.0.0.1:5555'. | |||
161 | """ |
|
162 | """ | |
162 | return self._address |
|
163 | return self._address | |
163 |
|
164 | |||
@@ -176,9 +177,9 b' class ZMQSocketChannel(Thread):' | |||||
176 | self.ioloop.add_callback(thread_send) |
|
177 | self.ioloop.add_callback(thread_send) | |
177 |
|
178 | |||
178 | def _handle_recv(self, msg): |
|
179 | def _handle_recv(self, msg): | |
179 |
""" |
|
180 | """Callback for stream.on_recv. | |
180 |
|
181 | |||
181 |
|
|
182 | Unpacks message, and calls handlers with it. | |
182 | """ |
|
183 | """ | |
183 | ident,smsg = self.session.feed_identities(msg) |
|
184 | ident,smsg = self.session.feed_identities(msg) | |
184 | self.call_handlers(self.session.unserialize(smsg)) |
|
185 | self.call_handlers(self.session.unserialize(smsg)) | |
@@ -186,8 +187,7 b' class ZMQSocketChannel(Thread):' | |||||
186 |
|
187 | |||
187 |
|
188 | |||
188 | class ShellChannel(ZMQSocketChannel): |
|
189 | class ShellChannel(ZMQSocketChannel): | |
189 |
"""The |
|
190 | """The shell channel for issuing request/replies to the kernel.""" | |
190 | """ |
|
|||
191 |
|
191 | |||
192 | command_queue = None |
|
192 | command_queue = None | |
193 | # flag for whether execute requests should be allowed to call raw_input: |
|
193 | # flag for whether execute requests should be allowed to call raw_input: | |
@@ -212,6 +212,7 b' class ShellChannel(ZMQSocketChannel):' | |||||
212 | pass |
|
212 | pass | |
213 |
|
213 | |||
214 | def stop(self): |
|
214 | def stop(self): | |
|
215 | """Stop the channel's event loop and join its thread.""" | |||
215 | self.ioloop.stop() |
|
216 | self.ioloop.stop() | |
216 | super(ShellChannel, self).stop() |
|
217 | super(ShellChannel, self).stop() | |
217 |
|
218 | |||
@@ -314,7 +315,7 b' class ShellChannel(ZMQSocketChannel):' | |||||
314 | return msg['header']['msg_id'] |
|
315 | return msg['header']['msg_id'] | |
315 |
|
316 | |||
316 | def object_info(self, oname, detail_level=0): |
|
317 | def object_info(self, oname, detail_level=0): | |
317 | """Get metadata information about an object. |
|
318 | """Get metadata information about an object in the kernel's namespace. | |
318 |
|
319 | |||
319 | Parameters |
|
320 | Parameters | |
320 | ---------- |
|
321 | ---------- | |
@@ -333,7 +334,7 b' class ShellChannel(ZMQSocketChannel):' | |||||
333 | return msg['header']['msg_id'] |
|
334 | return msg['header']['msg_id'] | |
334 |
|
335 | |||
335 | def history(self, raw=True, output=False, hist_access_type='range', **kwargs): |
|
336 | def history(self, raw=True, output=False, hist_access_type='range', **kwargs): | |
336 | """Get entries from the history list. |
|
337 | """Get entries from the kernel's history list. | |
337 |
|
338 | |||
338 | Parameters |
|
339 | Parameters | |
339 | ---------- |
|
340 | ---------- | |
@@ -396,7 +397,9 b' class ShellChannel(ZMQSocketChannel):' | |||||
396 |
|
397 | |||
397 |
|
398 | |||
398 | class IOPubChannel(ZMQSocketChannel): |
|
399 | class IOPubChannel(ZMQSocketChannel): | |
399 |
"""The |
|
400 | """The iopub channel which listens for messages that the kernel publishes. | |
|
401 | ||||
|
402 | This channel is where all output is published to frontends. | |||
400 | """ |
|
403 | """ | |
401 |
|
404 | |||
402 | def __init__(self, context, session, address): |
|
405 | def __init__(self, context, session, address): | |
@@ -418,6 +421,7 b' class IOPubChannel(ZMQSocketChannel):' | |||||
418 | pass |
|
421 | pass | |
419 |
|
422 | |||
420 | def stop(self): |
|
423 | def stop(self): | |
|
424 | """Stop the channel's event loop and join its thread.""" | |||
421 | self.ioloop.stop() |
|
425 | self.ioloop.stop() | |
422 | super(IOPubChannel, self).stop() |
|
426 | super(IOPubChannel, self).stop() | |
423 |
|
427 | |||
@@ -432,7 +436,7 b' class IOPubChannel(ZMQSocketChannel):' | |||||
432 | raise NotImplementedError('call_handlers must be defined in a subclass.') |
|
436 | raise NotImplementedError('call_handlers must be defined in a subclass.') | |
433 |
|
437 | |||
434 | def flush(self, timeout=1.0): |
|
438 | def flush(self, timeout=1.0): | |
435 |
"""Immediately processes all pending messages on the |
|
439 | """Immediately processes all pending messages on the iopub channel. | |
436 |
|
440 | |||
437 | Callers should use this method to ensure that :method:`call_handlers` |
|
441 | Callers should use this method to ensure that :method:`call_handlers` | |
438 | has been called for all messages that have been received on the |
|
442 | has been called for all messages that have been received on the | |
@@ -462,7 +466,7 b' class IOPubChannel(ZMQSocketChannel):' | |||||
462 |
|
466 | |||
463 |
|
467 | |||
464 | class StdInChannel(ZMQSocketChannel): |
|
468 | class StdInChannel(ZMQSocketChannel): | |
465 |
""" |
|
469 | """The stdin channel to handle raw_input requests that the kernel makes.""" | |
466 |
|
470 | |||
467 | msg_queue = None |
|
471 | msg_queue = None | |
468 |
|
472 | |||
@@ -482,9 +486,9 b' class StdInChannel(ZMQSocketChannel):' | |||||
482 | self.socket.close() |
|
486 | self.socket.close() | |
483 | except: |
|
487 | except: | |
484 | pass |
|
488 | pass | |
485 |
|
||||
486 |
|
489 | |||
487 | def stop(self): |
|
490 | def stop(self): | |
|
491 | """Stop the channel's event loop and join its thread.""" | |||
488 | self.ioloop.stop() |
|
492 | self.ioloop.stop() | |
489 | super(StdInChannel, self).stop() |
|
493 | super(StdInChannel, self).stop() | |
490 |
|
494 | |||
@@ -538,7 +542,7 b' class HBChannel(ZMQSocketChannel):' | |||||
538 | self.poller.register(self.socket, zmq.POLLIN) |
|
542 | self.poller.register(self.socket, zmq.POLLIN) | |
539 |
|
543 | |||
540 | def _poll(self, start_time): |
|
544 | def _poll(self, start_time): | |
541 | """poll for heartbeat replies until we reach self.time_to_dead |
|
545 | """poll for heartbeat replies until we reach self.time_to_dead. | |
542 |
|
546 | |||
543 | Ignores interrupts, and returns the result of poll(), which |
|
547 | Ignores interrupts, and returns the result of poll(), which | |
544 | will be an empty list if no messages arrived before the timeout, |
|
548 | will be an empty list if no messages arrived before the timeout, | |
@@ -627,6 +631,7 b' class HBChannel(ZMQSocketChannel):' | |||||
627 | return False |
|
631 | return False | |
628 |
|
632 | |||
629 | def stop(self): |
|
633 | def stop(self): | |
|
634 | """Stop the channel's event loop and join its thread.""" | |||
630 | self._running = False |
|
635 | self._running = False | |
631 | super(HBChannel, self).stop() |
|
636 | super(HBChannel, self).stop() | |
632 |
|
637 | |||
@@ -646,15 +651,21 b' class HBChannel(ZMQSocketChannel):' | |||||
646 | #----------------------------------------------------------------------------- |
|
651 | #----------------------------------------------------------------------------- | |
647 |
|
652 | |||
648 | class KernelManager(Configurable): |
|
653 | class KernelManager(Configurable): | |
649 | """ Manages a kernel for a frontend. |
|
654 | """Manages a single kernel on this host along with its channels. | |
650 |
|
655 | |||
651 | The SUB channel is for the frontend to receive messages published by the |
|
656 | There are four channels associated with each kernel: | |
652 | kernel. |
|
|||
653 |
|
657 | |||
654 | The REQ channel is for the frontend to make requests of the kernel. |
|
658 | * shell: for request/reply calls to the kernel. | |
|
659 | * iopub: for the kernel to publish results to frontends. | |||
|
660 | * hb: for monitoring the kernel's heartbeat. | |||
|
661 | * stdin: for frontends to reply to raw_input calls in the kernel. | |||
655 |
|
662 | |||
656 | The REP channel is for the kernel to request stdin (raw_input) from the |
|
663 | The usage of the channels that this class manages is optional. It is | |
657 | frontend. |
|
664 | entirely possible to connect to the kernels directly using ZeroMQ | |
|
665 | sockets. These channels are useful primarily for talking to a kernel | |||
|
666 | whose :class:`KernelManager` is in the same process. | |||
|
667 | ||||
|
668 | This version manages kernels started using Popen. | |||
658 | """ |
|
669 | """ | |
659 | # The PyZMQ Context to use for communication with the kernel. |
|
670 | # The PyZMQ Context to use for communication with the kernel. | |
660 | context = Instance(zmq.Context) |
|
671 | context = Instance(zmq.Context) | |
@@ -708,9 +719,10 b' class KernelManager(Configurable):' | |||||
708 | """Starts the channels for this kernel. |
|
719 | """Starts the channels for this kernel. | |
709 |
|
720 | |||
710 | This will create the channels if they do not exist and then start |
|
721 | This will create the channels if they do not exist and then start | |
711 | them. If port numbers of 0 are being used (random ports) then you |
|
722 | them (their activity runs in a thread). If port numbers of 0 are | |
712 | must first call :method:`start_kernel`. If the channels have been |
|
723 | being used (random ports) then you must first call | |
713 | stopped and you call this, :class:`RuntimeError` will be raised. |
|
724 | :method:`start_kernel`. If the channels have been stopped and you | |
|
725 | call this, :class:`RuntimeError` will be raised. | |||
714 | """ |
|
726 | """ | |
715 | if shell: |
|
727 | if shell: | |
716 | self.shell_channel.start() |
|
728 | self.shell_channel.start() | |
@@ -726,6 +738,8 b' class KernelManager(Configurable):' | |||||
726 |
|
738 | |||
727 | def stop_channels(self): |
|
739 | def stop_channels(self): | |
728 | """Stops all the running channels for this kernel. |
|
740 | """Stops all the running channels for this kernel. | |
|
741 | ||||
|
742 | This stops their event loops and joins their threads. | |||
729 | """ |
|
743 | """ | |
730 | if self.shell_channel.is_alive(): |
|
744 | if self.shell_channel.is_alive(): | |
731 | self.shell_channel.stop() |
|
745 | self.shell_channel.stop() | |
@@ -743,7 +757,13 b' class KernelManager(Configurable):' | |||||
743 | self.stdin_channel.is_alive() or self.hb_channel.is_alive()) |
|
757 | self.stdin_channel.is_alive() or self.hb_channel.is_alive()) | |
744 |
|
758 | |||
745 | def _make_url(self, port): |
|
759 | def _make_url(self, port): | |
746 |
""" |
|
760 | """Make a zmq url with a port. | |
|
761 | ||||
|
762 | There are two cases that this handles: | |||
|
763 | ||||
|
764 | * tcp: tcp://ip:port | |||
|
765 | * ipc: ipc://ip-port | |||
|
766 | """ | |||
747 | if self.transport == 'tcp': |
|
767 | if self.transport == 'tcp': | |
748 | return "tcp://%s:%i" % (self.ip, port) |
|
768 | return "tcp://%s:%i" % (self.ip, port) | |
749 | else: |
|
769 | else: | |
@@ -751,42 +771,37 b' class KernelManager(Configurable):' | |||||
751 |
|
771 | |||
752 | @property |
|
772 | @property | |
753 | def shell_channel(self): |
|
773 | def shell_channel(self): | |
754 |
"""Get the |
|
774 | """Get the shell channel object for this kernel.""" | |
755 | if self._shell_channel is None: |
|
775 | if self._shell_channel is None: | |
756 |
self._shell_channel = self.shell_channel_class( |
|
776 | self._shell_channel = self.shell_channel_class( | |
757 | self.session, |
|
777 | self.context, self.session, self._make_url(self.shell_port) | |
758 | self._make_url(self.shell_port), |
|
|||
759 | ) |
|
778 | ) | |
760 | return self._shell_channel |
|
779 | return self._shell_channel | |
761 |
|
780 | |||
762 | @property |
|
781 | @property | |
763 | def iopub_channel(self): |
|
782 | def iopub_channel(self): | |
764 |
"""Get the |
|
783 | """Get the iopub channel object for this kernel.""" | |
765 | if self._iopub_channel is None: |
|
784 | if self._iopub_channel is None: | |
766 |
self._iopub_channel = self.iopub_channel_class( |
|
785 | self._iopub_channel = self.iopub_channel_class( | |
767 | self.session, |
|
786 | self.context, self.session, self._make_url(self.iopub_port) | |
768 | self._make_url(self.iopub_port), |
|
|||
769 | ) |
|
787 | ) | |
770 | return self._iopub_channel |
|
788 | return self._iopub_channel | |
771 |
|
789 | |||
772 | @property |
|
790 | @property | |
773 | def stdin_channel(self): |
|
791 | def stdin_channel(self): | |
774 |
"""Get the |
|
792 | """Get the stdin channel object for this kernel.""" | |
775 | if self._stdin_channel is None: |
|
793 | if self._stdin_channel is None: | |
776 |
self._stdin_channel = self.stdin_channel_class( |
|
794 | self._stdin_channel = self.stdin_channel_class( | |
777 | self.session, |
|
795 | self.context, self.session, self._make_url(self.stdin_port) | |
778 | self._make_url(self.stdin_port), |
|
|||
779 | ) |
|
796 | ) | |
780 | return self._stdin_channel |
|
797 | return self._stdin_channel | |
781 |
|
798 | |||
782 | @property |
|
799 | @property | |
783 | def hb_channel(self): |
|
800 | def hb_channel(self): | |
784 |
"""Get the h |
|
801 | """Get the hb channel object for this kernel.""" | |
785 | kernel is alive.""" |
|
|||
786 | if self._hb_channel is None: |
|
802 | if self._hb_channel is None: | |
787 |
self._hb_channel = self.hb_channel_class( |
|
803 | self._hb_channel = self.hb_channel_class( | |
788 | self.session, |
|
804 | self.context, self.session, self._make_url(self.hb_port) | |
789 | self._make_url(self.hb_port), |
|
|||
790 | ) |
|
805 | ) | |
791 | return self._hb_channel |
|
806 | return self._hb_channel | |
792 |
|
807 | |||
@@ -795,7 +810,7 b' class KernelManager(Configurable):' | |||||
795 | #-------------------------------------------------------------------------- |
|
810 | #-------------------------------------------------------------------------- | |
796 |
|
811 | |||
797 | def cleanup_connection_file(self): |
|
812 | def cleanup_connection_file(self): | |
798 |
""" |
|
813 | """Cleanup connection file *if we wrote it* | |
799 |
|
814 | |||
800 | Will not raise if the connection file was already removed somehow. |
|
815 | Will not raise if the connection file was already removed somehow. | |
801 | """ |
|
816 | """ | |
@@ -810,7 +825,7 b' class KernelManager(Configurable):' | |||||
810 | self.cleanup_ipc_files() |
|
825 | self.cleanup_ipc_files() | |
811 |
|
826 | |||
812 | def cleanup_ipc_files(self): |
|
827 | def cleanup_ipc_files(self): | |
813 |
""" |
|
828 | """Cleanup ipc files if we wrote them.""" | |
814 | if self.transport != 'ipc': |
|
829 | if self.transport != 'ipc': | |
815 | return |
|
830 | return | |
816 | for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port): |
|
831 | for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port): | |
@@ -821,7 +836,7 b' class KernelManager(Configurable):' | |||||
821 | pass |
|
836 | pass | |
822 |
|
837 | |||
823 | def load_connection_file(self): |
|
838 | def load_connection_file(self): | |
824 |
""" |
|
839 | """Load connection info from JSON dict in self.connection_file.""" | |
825 | with open(self.connection_file) as f: |
|
840 | with open(self.connection_file) as f: | |
826 | cfg = json.loads(f.read()) |
|
841 | cfg = json.loads(f.read()) | |
827 |
|
842 | |||
@@ -836,7 +851,7 b' class KernelManager(Configurable):' | |||||
836 | self.session.key = str_to_bytes(cfg['key']) |
|
851 | self.session.key = str_to_bytes(cfg['key']) | |
837 |
|
852 | |||
838 | def write_connection_file(self): |
|
853 | def write_connection_file(self): | |
839 |
""" |
|
854 | """Write connection info to JSON dict in self.connection_file.""" | |
840 | if self._connection_file_written: |
|
855 | if self._connection_file_written: | |
841 | return |
|
856 | return | |
842 | self.connection_file,cfg = write_connection_file(self.connection_file, |
|
857 | self.connection_file,cfg = write_connection_file(self.connection_file, | |
@@ -856,7 +871,7 b' class KernelManager(Configurable):' | |||||
856 | #-------------------------------------------------------------------------- |
|
871 | #-------------------------------------------------------------------------- | |
857 |
|
872 | |||
858 | def start_kernel(self, **kw): |
|
873 | def start_kernel(self, **kw): | |
859 | """Starts a kernel process and configures the manager to use it. |
|
874 | """Starts a kernel on this host in a separate process. | |
860 |
|
875 | |||
861 | If random ports (port=0) are being used, this method must be called |
|
876 | If random ports (port=0) are being used, this method must be called | |
862 | before the channels are created. |
|
877 | before the channels are created. | |
@@ -869,7 +884,8 b' class KernelManager(Configurable):' | |||||
869 | it should not be necessary to use this parameter. |
|
884 | it should not be necessary to use this parameter. | |
870 |
|
885 | |||
871 | **kw : optional |
|
886 | **kw : optional | |
872 | See respective options for IPython and Python kernels. |
|
887 | keyword arguments that are passed down into the launcher | |
|
888 | callable. | |||
873 | """ |
|
889 | """ | |
874 | if self.transport == 'tcp' and self.ip not in LOCAL_IPS: |
|
890 | if self.transport == 'tcp' and self.ip not in LOCAL_IPS: | |
875 | raise RuntimeError("Can only launch a kernel on a local interface. " |
|
891 | raise RuntimeError("Can only launch a kernel on a local interface. " | |
@@ -888,9 +904,22 b' class KernelManager(Configurable):' | |||||
888 | self.kernel = launch_kernel(fname=self.connection_file, **kw) |
|
904 | self.kernel = launch_kernel(fname=self.connection_file, **kw) | |
889 |
|
905 | |||
890 | def shutdown_kernel(self, now=False, restart=False): |
|
906 | def shutdown_kernel(self, now=False, restart=False): | |
891 |
""" |
|
907 | """Attempts to the stop the kernel process cleanly. | |
|
908 | ||||
|
909 | This attempts to shutdown the kernels cleanly by: | |||
|
910 | ||||
|
911 | 1. Sending it a shutdown message over the shell channel. | |||
|
912 | 2. If that fails, the kernel is shutdown forcibly by sending it | |||
|
913 | a signal. | |||
892 |
|
914 | |||
893 | If the kernel cannot be stopped and the kernel is local, it is killed. |
|
915 | Parameters: | |
|
916 | ----------- | |||
|
917 | now : bool | |||
|
918 | Should the kernel be forcible killed *now*. This skips the | |||
|
919 | first, nice shutdown attempt. | |||
|
920 | restart: bool | |||
|
921 | Will this kernel be restarted after it is shutdown. When this | |||
|
922 | is True, connection files will not be cleaned up. | |||
894 | """ |
|
923 | """ | |
895 | # FIXME: Shutdown does not work on Windows due to ZMQ errors! |
|
924 | # FIXME: Shutdown does not work on Windows due to ZMQ errors! | |
896 | if sys.platform == 'win32': |
|
925 | if sys.platform == 'win32': | |
@@ -928,7 +957,7 b' class KernelManager(Configurable):' | |||||
928 | """Restarts a kernel with the arguments that were used to launch it. |
|
957 | """Restarts a kernel with the arguments that were used to launch it. | |
929 |
|
958 | |||
930 | If the old kernel was launched with random ports, the same ports will be |
|
959 | If the old kernel was launched with random ports, the same ports will be | |
931 | used for the new kernel. |
|
960 | used for the new kernel. The same connection file is used again. | |
932 |
|
961 | |||
933 | Parameters |
|
962 | Parameters | |
934 | ---------- |
|
963 | ---------- | |
@@ -941,7 +970,7 b' class KernelManager(Configurable):' | |||||
941 | it is given a chance to perform a clean shutdown or not. |
|
970 | it is given a chance to perform a clean shutdown or not. | |
942 |
|
971 | |||
943 | **kw : optional |
|
972 | **kw : optional | |
944 |
Any options specified here will |
|
973 | Any options specified here will overwrite those used to launch the | |
945 | kernel. |
|
974 | kernel. | |
946 | """ |
|
975 | """ | |
947 | if self._launch_args is None: |
|
976 | if self._launch_args is None: | |
@@ -962,15 +991,13 b' class KernelManager(Configurable):' | |||||
962 |
|
991 | |||
963 | @property |
|
992 | @property | |
964 | def has_kernel(self): |
|
993 | def has_kernel(self): | |
965 | """Returns whether a kernel process has been specified for the kernel |
|
994 | """Has a kernel been started that we are managing.""" | |
966 | manager. |
|
|||
967 | """ |
|
|||
968 | return self.kernel is not None |
|
995 | return self.kernel is not None | |
969 |
|
996 | |||
970 | def kill_kernel(self): |
|
997 | def kill_kernel(self): | |
971 |
""" |
|
998 | """Kill the running kernel. | |
972 |
|
999 | |||
973 | This method blocks until the kernel process has terminated. |
|
1000 | This is a private method, callers should use shutdown_kernel(now=True). | |
974 | """ |
|
1001 | """ | |
975 | if self.has_kernel: |
|
1002 | if self.has_kernel: | |
976 | # Pause the heart beat channel if it exists. |
|
1003 | # Pause the heart beat channel if it exists. | |
@@ -1001,7 +1028,7 b' class KernelManager(Configurable):' | |||||
1001 | raise RuntimeError("Cannot kill kernel. No kernel is running!") |
|
1028 | raise RuntimeError("Cannot kill kernel. No kernel is running!") | |
1002 |
|
1029 | |||
1003 | def interrupt_kernel(self): |
|
1030 | def interrupt_kernel(self): | |
1004 |
""" |
|
1031 | """Interrupts the kernel by sending it a signal. | |
1005 |
|
1032 | |||
1006 | Unlike ``signal_kernel``, this operation is well supported on all |
|
1033 | Unlike ``signal_kernel``, this operation is well supported on all | |
1007 | platforms. |
|
1034 | platforms. | |
@@ -1016,7 +1043,7 b' class KernelManager(Configurable):' | |||||
1016 | raise RuntimeError("Cannot interrupt kernel. No kernel is running!") |
|
1043 | raise RuntimeError("Cannot interrupt kernel. No kernel is running!") | |
1017 |
|
1044 | |||
1018 | def signal_kernel(self, signum): |
|
1045 | def signal_kernel(self, signum): | |
1019 |
""" |
|
1046 | """Sends a signal to the kernel. | |
1020 |
|
1047 | |||
1021 | Note that since only SIGTERM is supported on Windows, this function is |
|
1048 | Note that since only SIGTERM is supported on Windows, this function is | |
1022 | only useful on Unix systems. |
|
1049 | only useful on Unix systems. | |
@@ -1053,3 +1080,4 b' IOPubChannelABC.register(IOPubChannel)' | |||||
1053 | HBChannelABC.register(HBChannel) |
|
1080 | HBChannelABC.register(HBChannel) | |
1054 | StdInChannelABC.register(StdInChannel) |
|
1081 | StdInChannelABC.register(StdInChannel) | |
1055 | KernelManagerABC.register(KernelManager) |
|
1082 | KernelManagerABC.register(KernelManager) | |
|
1083 |
General Comments 0
You need to be logged in to leave comments.
Login now