##// END OF EJS Templates
Minor debug statement removed.
Brian Granger -
Show More
@@ -1,192 +1,191 b''
1 1 """ Defines helper functions for creating kernel entry points and process
2 2 launchers.
3 3 """
4 4
5 5 # Standard library imports.
6 6 import socket
7 7 from subprocess import Popen
8 8 import sys
9 9
10 10 # System library imports.
11 11 import zmq
12 12
13 13 # Local imports.
14 14 from IPython.external.argparse import ArgumentParser
15 15 from exitpoller import ExitPollerUnix, ExitPollerWindows
16 16 from displayhook import DisplayHook
17 17 from iostream import OutStream
18 18 from session import Session
19 19
20 20
21 21 def bind_port(socket, ip, port):
22 22 """ Binds the specified ZMQ socket. If the port is zero, a random port is
23 23 chosen. Returns the port that was bound.
24 24 """
25 25 connection = 'tcp://%s' % ip
26 26 if port <= 0:
27 27 port = socket.bind_to_random_port(connection)
28 28 else:
29 29 connection += ':%i' % port
30 30 socket.bind(connection)
31 31 return port
32 32
33 33
34 34 def make_argument_parser():
35 35 """ Creates an ArgumentParser for the generic arguments supported by all
36 36 kernel entry points.
37 37 """
38 38 parser = ArgumentParser()
39 39 parser.add_argument('--ip', type=str, default='127.0.0.1',
40 40 help='set the kernel\'s IP address [default: local]')
41 41 parser.add_argument('--xrep', type=int, metavar='PORT', default=0,
42 42 help='set the XREP channel port [default: random]')
43 43 parser.add_argument('--pub', type=int, metavar='PORT', default=0,
44 44 help='set the PUB channel port [default: random]')
45 45 parser.add_argument('--req', type=int, metavar='PORT', default=0,
46 46 help='set the REQ channel port [default: random]')
47 47
48 48 if sys.platform == 'win32':
49 49 parser.add_argument('--parent', type=int, metavar='HANDLE',
50 50 default=0, help='kill this process if the process '
51 51 'with HANDLE dies')
52 52 else:
53 53 parser.add_argument('--parent', action='store_true',
54 54 help='kill this process if its parent dies')
55 55
56 56 return parser
57 57
58 58
59 59 def make_kernel(namespace, kernel_factory,
60 60 out_stream_factory=None, display_hook_factory=None):
61 61 """ Creates a kernel.
62 62 """
63 63 # Create a context, a session, and the kernel sockets.
64 64 print >>sys.__stdout__, "Starting the kernel..."
65 65 context = zmq.Context()
66 66 session = Session(username=u'kernel')
67 67
68 68 reply_socket = context.socket(zmq.XREP)
69 69 xrep_port = bind_port(reply_socket, namespace.ip, namespace.xrep)
70 70 print >>sys.__stdout__, "XREP Channel on port", xrep_port
71 71
72 72 pub_socket = context.socket(zmq.PUB)
73 73 pub_port = bind_port(pub_socket, namespace.ip, namespace.pub)
74 74 print >>sys.__stdout__, "PUB Channel on port", pub_port
75 75
76 76 req_socket = context.socket(zmq.XREQ)
77 77 req_port = bind_port(req_socket, namespace.ip, namespace.req)
78 78 print >>sys.__stdout__, "REQ Channel on port", req_port
79 79
80 80 # Redirect input streams and set a display hook.
81 81 if out_stream_factory:
82 pass
83 82 sys.stdout = out_stream_factory(session, pub_socket, u'stdout')
84 83 sys.stderr = out_stream_factory(session, pub_socket, u'stderr')
85 84 if display_hook_factory:
86 85 sys.displayhook = display_hook_factory(session, pub_socket)
87 86
88 87 # Create the kernel.
89 88 return kernel_factory(session=session, reply_socket=reply_socket,
90 89 pub_socket=pub_socket, req_socket=req_socket)
91 90
92 91
93 92 def start_kernel(namespace, kernel):
94 93 """ Starts a kernel.
95 94 """
96 95 # Configure this kernel/process to die on parent termination, if necessary.
97 96 if namespace.parent:
98 97 if sys.platform == 'win32':
99 98 poller = ExitPollerWindows(namespace.parent)
100 99 else:
101 100 poller = ExitPollerUnix()
102 101 poller.start()
103 102
104 103 # Start the kernel mainloop.
105 104 kernel.start()
106 105
107 106
108 107 def make_default_main(kernel_factory):
109 108 """ Creates the simplest possible kernel entry point.
110 109 """
111 110 def main():
112 111 namespace = make_argument_parser().parse_args()
113 112 kernel = make_kernel(namespace, kernel_factory, OutStream, DisplayHook)
114 113 start_kernel(namespace, kernel)
115 114 return main
116 115
117 116
118 117 def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0,
119 118 independent=False, extra_arguments=[]):
120 119 """ Launches a localhost kernel, binding to the specified ports.
121 120
122 121 Parameters
123 122 ----------
124 123 code : str,
125 124 A string of Python code that imports and executes a kernel entry point.
126 125
127 126 xrep_port : int, optional
128 127 The port to use for XREP channel.
129 128
130 129 pub_port : int, optional
131 130 The port to use for the SUB channel.
132 131
133 132 req_port : int, optional
134 133 The port to use for the REQ (raw input) channel.
135 134
136 135 independent : bool, optional (default False)
137 136 If set, the kernel process is guaranteed to survive if this process
138 137 dies. If not set, an effort is made to ensure that the kernel is killed
139 138 when this process dies. Note that in this case it is still good practice
140 139 to kill kernels manually before exiting.
141 140
142 141 extra_arguments = list, optional
143 142 A list of extra arguments to pass when executing the launch code.
144 143
145 144 Returns
146 145 -------
147 146 A tuple of form:
148 147 (kernel_process, xrep_port, pub_port, req_port)
149 148 where kernel_process is a Popen object and the ports are integers.
150 149 """
151 150 # Find open ports as necessary.
152 151 ports = []
153 152 ports_needed = int(xrep_port <= 0) + int(pub_port <= 0) + int(req_port <= 0)
154 153 for i in xrange(ports_needed):
155 154 sock = socket.socket()
156 155 sock.bind(('', 0))
157 156 ports.append(sock)
158 157 for i, sock in enumerate(ports):
159 158 port = sock.getsockname()[1]
160 159 sock.close()
161 160 ports[i] = port
162 161 if xrep_port <= 0:
163 162 xrep_port = ports.pop(0)
164 163 if pub_port <= 0:
165 164 pub_port = ports.pop(0)
166 165 if req_port <= 0:
167 166 req_port = ports.pop(0)
168 167
169 168 # Build the kernel launch command.
170 169 arguments = [ sys.executable, '-c', code, '--xrep', str(xrep_port),
171 170 '--pub', str(pub_port), '--req', str(req_port) ]
172 171 arguments.extend(extra_arguments)
173 172
174 173 # Spawn a kernel.
175 174 if independent:
176 175 if sys.platform == 'win32':
177 176 proc = Popen(['start', '/b'] + arguments, shell=True)
178 177 else:
179 178 proc = Popen(arguments, preexec_fn=lambda: os.setsid())
180 179 else:
181 180 if sys.platform == 'win32':
182 181 from _subprocess import DuplicateHandle, GetCurrentProcess, \
183 182 DUPLICATE_SAME_ACCESS
184 183 pid = GetCurrentProcess()
185 184 handle = DuplicateHandle(pid, pid, pid, 0,
186 185 True, # Inheritable by new processes.
187 186 DUPLICATE_SAME_ACCESS)
188 187 proc = Popen(arguments + ['--parent', str(int(handle))])
189 188 else:
190 189 proc = Popen(arguments + ['--parent'])
191 190
192 191 return proc, xrep_port, pub_port, req_port
General Comments 0
You need to be logged in to leave comments. Login now