##// END OF EJS Templates
remove special handling of ipython_kernel in launcher...
Min RK -
Show More
@@ -101,25 +101,13 b" def make_ipkernel_cmd(mod='IPython.kernel', executable=None, extra_arguments=[],"
101 executable = sys.executable
101 executable = sys.executable
102 arguments = [ executable, '-m', mod, '-f', '{connection_file}' ]
102 arguments = [ executable, '-m', mod, '-f', '{connection_file}' ]
103 arguments.extend(extra_arguments)
103 arguments.extend(extra_arguments)
104
104
105 if sys.platform == 'win32':
106
107 # If the kernel is running on pythonw and stdout/stderr are not been
108 # re-directed, it will crash when more than 4KB of data is written to
109 # stdout or stderr. This is a bug that has been with Python for a very
110 # long time; see http://bugs.python.org/issue706263.
111 # A cleaner solution to this problem would be to pass os.devnull to
112 # Popen directly. Unfortunately, that does not work.
113 if executable.endswith('pythonw.exe'):
114 arguments.append('--no-stdout')
115 arguments.append('--no-stderr')
116
117 return arguments
105 return arguments
118
106
119
107
120 def launch_kernel(cmd, stdin=None, stdout=None, stderr=None, env=None,
108 def launch_kernel(cmd, stdin=None, stdout=None, stderr=None, env=None,
121 independent=False,
109 independent=False,
122 cwd=None, ipython_kernel=True,
110 cwd=None,
123 **kw
111 **kw
124 ):
112 ):
125 """ Launches a localhost kernel, binding to the specified ports.
113 """ Launches a localhost kernel, binding to the specified ports.
@@ -141,10 +129,6 b' def launch_kernel(cmd, stdin=None, stdout=None, stderr=None, env=None,'
141 cwd : path, optional
129 cwd : path, optional
142 The working dir of the kernel process (default: cwd of this process).
130 The working dir of the kernel process (default: cwd of this process).
143
131
144 ipython_kernel : bool, optional
145 Whether the kernel is an official IPython one,
146 and should get a bit of special treatment.
147
148 Returns
132 Returns
149 -------
133 -------
150
134
@@ -166,14 +150,22 b' def launch_kernel(cmd, stdin=None, stdout=None, stderr=None, env=None,'
166 # stderr are all invalid.
150 # stderr are all invalid.
167 redirect_out = sys.executable.endswith('pythonw.exe')
151 redirect_out = sys.executable.endswith('pythonw.exe')
168 if redirect_out:
152 if redirect_out:
169 _stdout = PIPE if stdout is None else stdout
153 blackhole = open(os.devnull, 'w')
170 _stderr = PIPE if stderr is None else stderr
154 _stdout = blackhole if stdout is None else stdout
155 _stderr = blackhole if stderr is None else stderr
171 else:
156 else:
172 _stdout, _stderr = stdout, stderr
157 _stdout, _stderr = stdout, stderr
173
158
174 env = env if (env is not None) else os.environ.copy()
159 env = env if (env is not None) else os.environ.copy()
175
160
176 encoding = getdefaultencoding(prefer_stream=False)
161 encoding = getdefaultencoding(prefer_stream=False)
162 kwargs = dict(
163 stdin=_stdin,
164 stdout=_stdout,
165 stderr=_stderr,
166 cwd=cwd,
167 env=env,
168 )
177
169
178 # Spawn a kernel.
170 # Spawn a kernel.
179 if sys.platform == 'win32':
171 if sys.platform == 'win32':
@@ -181,73 +173,47 b' def launch_kernel(cmd, stdin=None, stdout=None, stderr=None, env=None,'
181 cmd = [ cast_bytes_py2(c, encoding) for c in cmd ]
173 cmd = [ cast_bytes_py2(c, encoding) for c in cmd ]
182 if cwd:
174 if cwd:
183 cwd = cast_bytes_py2(cwd, sys.getfilesystemencoding() or 'ascii')
175 cwd = cast_bytes_py2(cwd, sys.getfilesystemencoding() or 'ascii')
176 kwargs['cwd'] = cwd
184
177
185 from IPython.kernel.zmq.parentpoller import ParentPollerWindows
178 from IPython.kernel.zmq.parentpoller import ParentPollerWindows
186 # Create a Win32 event for interrupting the kernel.
179 # Create a Win32 event for interrupting the kernel
180 # and store it in an environment variable.
187 interrupt_event = ParentPollerWindows.create_interrupt_event()
181 interrupt_event = ParentPollerWindows.create_interrupt_event()
188 # Store this in an environment variable for third party kernels, but at
182 env["JPY_INTERRUPT_EVENT"] = str(interrupt_event)
189 # present, our own kernel expects this as a command line argument.
183
190 env["IPY_INTERRUPT_EVENT"] = str(interrupt_event)
184 try:
191 if ipython_kernel:
185 from _winapi import DuplicateHandle, GetCurrentProcess, \
192 cmd += [ '--interrupt=%i' % interrupt_event ]
186 DUPLICATE_SAME_ACCESS, CREATE_NEW_PROCESS_GROUP
193
187 except:
194 # If the kernel is running on pythonw and stdout/stderr are not been
188 from _subprocess import DuplicateHandle, GetCurrentProcess, \
195 # re-directed, it will crash when more than 4KB of data is written to
189 DUPLICATE_SAME_ACCESS, CREATE_NEW_PROCESS_GROUP
196 # stdout or stderr. This is a bug that has been with Python for a very
190 # Launch the kernel process
197 # long time; see http://bugs.python.org/issue706263.
198 # A cleaner solution to this problem would be to pass os.devnull to
199 # Popen directly. Unfortunately, that does not work.
200 if cmd[0].endswith('pythonw.exe'):
201 if stdout is None:
202 cmd.append('--no-stdout')
203 if stderr is None:
204 cmd.append('--no-stderr')
205
206 # Launch the kernel process.
207 if independent:
191 if independent:
208 proc = Popen(cmd,
192 kwargs['creationflags'] = CREATE_NEW_PROCESS_GROUP
209 creationflags=512, # CREATE_NEW_PROCESS_GROUP
210 stdin=_stdin, stdout=_stdout, stderr=_stderr, env=env)
211 else:
193 else:
212 if ipython_kernel:
194 pid = GetCurrentProcess()
213 try:
195 handle = DuplicateHandle(pid, pid, pid, 0,
214 from _winapi import DuplicateHandle, GetCurrentProcess, \
196 True, # Inheritable by new processes.
215 DUPLICATE_SAME_ACCESS
197 DUPLICATE_SAME_ACCESS)
216 except:
198 env['JPY_PARENT_PID'] = str(handle)
217 from _subprocess import DuplicateHandle, GetCurrentProcess, \
199
218 DUPLICATE_SAME_ACCESS
200 proc = Popen(cmd, **kwargs)
219 pid = GetCurrentProcess()
220 handle = DuplicateHandle(pid, pid, pid, 0,
221 True, # Inheritable by new processes.
222 DUPLICATE_SAME_ACCESS)
223 cmd +=[ '--parent=%i' % handle ]
224
225
226 proc = Popen(cmd,
227 stdin=_stdin, stdout=_stdout, stderr=_stderr, cwd=cwd, env=env)
228
201
229 # Attach the interrupt event to the Popen objet so it can be used later.
202 # Attach the interrupt event to the Popen objet so it can be used later.
230 proc.win32_interrupt_event = interrupt_event
203 proc.win32_interrupt_event = interrupt_event
231
204
232 else:
205 else:
233 if independent:
206 if independent:
234 proc = Popen(cmd, preexec_fn=lambda: os.setsid(),
207 kwargs['preexec_fn'] = lambda: os.setsid()
235 stdin=_stdin, stdout=_stdout, stderr=_stderr, cwd=cwd, env=env)
236 else:
208 else:
237 if ipython_kernel:
209 env['JPY_PARENT_PID'] = str(os.getpid())
238 cmd += ['--parent=1']
210
239 proc = Popen(cmd,
211 proc = Popen(cmd, **kwargs)
240 stdin=_stdin, stdout=_stdout, stderr=_stderr, cwd=cwd, env=env)
241
212
242 # Clean up pipes created to work around Popen bug.
213 # Clean up pipes created to work around Popen bug.
243 if redirect_in:
214 if redirect_in:
244 if stdin is None:
215 if stdin is None:
245 proc.stdin.close()
216 proc.stdin.close()
246 if redirect_out:
247 if stdout is None:
248 proc.stdout.close()
249 if stderr is None:
250 proc.stderr.close()
251
217
252 return proc
218 return proc
253
219
@@ -237,7 +237,6 b' class KernelManager(ConnectionFileMixin):'
237 env.update(self.kernel_spec.env or {})
237 env.update(self.kernel_spec.env or {})
238 # launch the kernel subprocess
238 # launch the kernel subprocess
239 self.kernel = self._launch_kernel(kernel_cmd, env=env,
239 self.kernel = self._launch_kernel(kernel_cmd, env=env,
240 ipython_kernel=self.ipython_kernel,
241 **kw)
240 **kw)
242 self.start_restarter()
241 self.start_restarter()
243 self._connect_control_socket()
242 self._connect_control_socket()
@@ -53,11 +53,8 b' kernel_aliases.update({'
53 'stdin' : 'IPKernelApp.stdin_port',
53 'stdin' : 'IPKernelApp.stdin_port',
54 'control' : 'IPKernelApp.control_port',
54 'control' : 'IPKernelApp.control_port',
55 'f' : 'IPKernelApp.connection_file',
55 'f' : 'IPKernelApp.connection_file',
56 'parent': 'IPKernelApp.parent_handle',
57 'transport': 'IPKernelApp.transport',
56 'transport': 'IPKernelApp.transport',
58 })
57 })
59 if sys.platform.startswith('win'):
60 kernel_aliases['interrupt'] = 'IPKernelApp.interrupt'
61
58
62 kernel_flags = dict(base_flags)
59 kernel_flags = dict(base_flags)
63 kernel_flags.update({
60 kernel_flags.update({
@@ -133,11 +130,11 b' class IPKernelApp(BaseIPythonApplication, InteractiveShellApp,'
133 config=True, help="The importstring for the DisplayHook factory")
130 config=True, help="The importstring for the DisplayHook factory")
134
131
135 # polling
132 # polling
136 parent_handle = Integer(0, config=True,
133 parent_handle = Integer(int(os.environ.get('JPY_PARENT_PID') or 0), config=True,
137 help="""kill this process if its parent dies. On Windows, the argument
134 help="""kill this process if its parent dies. On Windows, the argument
138 specifies the HANDLE of the parent process, otherwise it is simply boolean.
135 specifies the HANDLE of the parent process, otherwise it is simply boolean.
139 """)
136 """)
140 interrupt = Integer(0, config=True,
137 interrupt = Integer(int(os.environ.get('JPY_INTERRUPT_EVENT') or 0), config=True,
141 help="""ONLY USED ON WINDOWS
138 help="""ONLY USED ON WINDOWS
142 Interrupt this process when the parent is signaled.
139 Interrupt this process when the parent is signaled.
143 """)
140 """)
General Comments 0
You need to be logged in to leave comments. Login now