##// END OF EJS Templates
split kernel.util into kernel.connect and kernel.launcher
MinRK -
Show More
@@ -1,4 +1,5 b''
1 """IPython kernel bases and utilities"""
1 """IPython kernel bases and utilities"""
2
2
3 from .connect import *
4 from .launcher import *
3 from .kernelmanagerabc import *
5 from .kernelmanagerabc import *
4 from .util import *
@@ -1,4 +1,4 b''
1 """Utilities for working with kernels and their connection files
1 """Utilities for connecting to kernels
2
2
3 Authors:
3 Authors:
4
4
@@ -337,233 +337,3 b' def tunnel_to_kernel(connection_info, sshserver, sshkey=None):'
337
337
338 return tuple(lports)
338 return tuple(lports)
339
339
340
341 #-----------------------------------------------------------------------------
342 # Launching Kernels
343 #-----------------------------------------------------------------------------
344
345 def swallow_argv(argv, aliases=None, flags=None):
346 """strip frontend-specific aliases and flags from an argument list
347
348 For use primarily in frontend apps that want to pass a subset of command-line
349 arguments through to a subprocess, where frontend-specific flags and aliases
350 should be removed from the list.
351
352 Parameters
353 ----------
354
355 argv : list(str)
356 The starting argv, to be filtered
357 aliases : container of aliases (dict, list, set, etc.)
358 The frontend-specific aliases to be removed
359 flags : container of flags (dict, list, set, etc.)
360 The frontend-specific flags to be removed
361
362 Returns
363 -------
364
365 argv : list(str)
366 The argv list, excluding flags and aliases that have been stripped
367 """
368
369 if aliases is None:
370 aliases = set()
371 if flags is None:
372 flags = set()
373
374 stripped = list(argv) # copy
375
376 swallow_next = False
377 was_flag = False
378 for a in argv:
379 if swallow_next:
380 swallow_next = False
381 # last arg was an alias, remove the next one
382 # *unless* the last alias has a no-arg flag version, in which
383 # case, don't swallow the next arg if it's also a flag:
384 if not (was_flag and a.startswith('-')):
385 stripped.remove(a)
386 continue
387 if a.startswith('-'):
388 split = a.lstrip('-').split('=')
389 alias = split[0]
390 if alias in aliases:
391 stripped.remove(a)
392 if len(split) == 1:
393 # alias passed with arg via space
394 swallow_next = True
395 # could have been a flag that matches an alias, e.g. `existing`
396 # in which case, we might not swallow the next arg
397 was_flag = alias in flags
398 elif alias in flags and len(split) == 1:
399 # strip flag, but don't swallow next, as flags don't take args
400 stripped.remove(a)
401
402 # return shortened list
403 return stripped
404
405
406 def make_ipkernel_cmd(code, executable=None, extra_arguments=[], **kw):
407 """Build Popen command list for launching an IPython kernel.
408
409 Parameters
410 ----------
411 code : str,
412 A string of Python code that imports and executes a kernel entry point.
413
414 executable : str, optional (default sys.executable)
415 The Python executable to use for the kernel process.
416
417 extra_arguments : list, optional
418 A list of extra arguments to pass when executing the launch code.
419
420 Returns
421 -------
422
423 A Popen command list
424 """
425
426 # Build the kernel launch command.
427 if executable is None:
428 executable = sys.executable
429 arguments = [ executable, '-c', code, '-f', '{connection_file}' ]
430 arguments.extend(extra_arguments)
431
432 # Spawn a kernel.
433 if sys.platform == 'win32':
434
435 # If the kernel is running on pythonw and stdout/stderr are not been
436 # re-directed, it will crash when more than 4KB of data is written to
437 # stdout or stderr. This is a bug that has been with Python for a very
438 # long time; see http://bugs.python.org/issue706263.
439 # A cleaner solution to this problem would be to pass os.devnull to
440 # Popen directly. Unfortunately, that does not work.
441 if executable.endswith('pythonw.exe'):
442 arguments.append('--no-stdout')
443 arguments.append('--no-stderr')
444
445 return arguments
446
447
448 def launch_kernel(cmd, stdin=None, stdout=None, stderr=None,
449 independent=False,
450 cwd=None, ipython_kernel=True,
451 **kw
452 ):
453 """ Launches a localhost kernel, binding to the specified ports.
454
455 Parameters
456 ----------
457 cmd : Popen list,
458 A string of Python code that imports and executes a kernel entry point.
459
460 stdin, stdout, stderr : optional (default None)
461 Standards streams, as defined in subprocess.Popen.
462
463 independent : bool, optional (default False)
464 If set, the kernel process is guaranteed to survive if this process
465 dies. If not set, an effort is made to ensure that the kernel is killed
466 when this process dies. Note that in this case it is still good practice
467 to kill kernels manually before exiting.
468
469 cwd : path, optional
470 The working dir of the kernel process (default: cwd of this process).
471
472 ipython_kernel : bool, optional
473 Whether the kernel is an official IPython one,
474 and should get a bit of special treatment.
475
476 Returns
477 -------
478
479 Popen instance for the kernel subprocess
480 """
481
482 # Popen will fail (sometimes with a deadlock) if stdin, stdout, and stderr
483 # are invalid. Unfortunately, there is in general no way to detect whether
484 # they are valid. The following two blocks redirect them to (temporary)
485 # pipes in certain important cases.
486
487 # If this process has been backgrounded, our stdin is invalid. Since there
488 # is no compelling reason for the kernel to inherit our stdin anyway, we'll
489 # place this one safe and always redirect.
490 redirect_in = True
491 _stdin = PIPE if stdin is None else stdin
492
493 # If this process in running on pythonw, we know that stdin, stdout, and
494 # stderr are all invalid.
495 redirect_out = sys.executable.endswith('pythonw.exe')
496 if redirect_out:
497 _stdout = PIPE if stdout is None else stdout
498 _stderr = PIPE if stderr is None else stderr
499 else:
500 _stdout, _stderr = stdout, stderr
501
502 # Spawn a kernel.
503 if sys.platform == 'win32':
504 from IPython.zmq.parentpoller import ParentPollerWindows
505 # Create a Win32 event for interrupting the kernel.
506 interrupt_event = ParentPollerWindows.create_interrupt_event()
507 if ipython_kernel:
508 cmd += [ '--interrupt=%i' % interrupt_event ]
509
510 # If the kernel is running on pythonw and stdout/stderr are not been
511 # re-directed, it will crash when more than 4KB of data is written to
512 # stdout or stderr. This is a bug that has been with Python for a very
513 # long time; see http://bugs.python.org/issue706263.
514 # A cleaner solution to this problem would be to pass os.devnull to
515 # Popen directly. Unfortunately, that does not work.
516 if cmd[0].endswith('pythonw.exe'):
517 if stdout is None:
518 cmd.append('--no-stdout')
519 if stderr is None:
520 cmd.append('--no-stderr')
521
522 # Launch the kernel process.
523 if independent:
524 proc = Popen(cmd,
525 creationflags=512, # CREATE_NEW_PROCESS_GROUP
526 stdin=_stdin, stdout=_stdout, stderr=_stderr)
527 else:
528 if ipython_kernel:
529 try:
530 from _winapi import DuplicateHandle, GetCurrentProcess, \
531 DUPLICATE_SAME_ACCESS
532 except:
533 from _subprocess import DuplicateHandle, GetCurrentProcess, \
534 DUPLICATE_SAME_ACCESS
535 pid = GetCurrentProcess()
536 handle = DuplicateHandle(pid, pid, pid, 0,
537 True, # Inheritable by new processes.
538 DUPLICATE_SAME_ACCESS)
539 cmd +=[ '--parent=%i' % handle ]
540
541
542 proc = Popen(cmd,
543 stdin=_stdin, stdout=_stdout, stderr=_stderr, cwd=cwd)
544
545 # Attach the interrupt event to the Popen objet so it can be used later.
546 proc.win32_interrupt_event = interrupt_event
547
548 else:
549 if independent:
550 proc = Popen(cmd, preexec_fn=lambda: os.setsid(),
551 stdin=_stdin, stdout=_stdout, stderr=_stderr, cwd=cwd)
552 else:
553 if ipython_kernel:
554 cmd += ['--parent=1']
555 proc = Popen(cmd,
556 stdin=_stdin, stdout=_stdout, stderr=_stderr, cwd=cwd)
557
558 # Clean up pipes created to work around Popen bug.
559 if redirect_in:
560 if stdin is None:
561 proc.stdin.close()
562 if redirect_out:
563 if stdout is None:
564 proc.stdout.close()
565 if stderr is None:
566 proc.stderr.close()
567
568 return proc
569
1 NO CONTENT: file renamed from IPython/kernel/tests/test_util.py to IPython/kernel/tests/test_launcher.py
NO CONTENT: file renamed from IPython/kernel/tests/test_util.py to IPython/kernel/tests/test_launcher.py
@@ -1,12 +1,12 b''
1 """[DEPRECATED] Utilities for connecting to kernels
1 """[DEPRECATED] Utilities for connecting to kernels
2
2
3 Moved to IPython.kernel.util
3 Moved to IPython.kernel.connect
4 """
4 """
5
5
6 import warnings
6 import warnings
7 warnings.warn("IPython.lib.kernel moved to IPython.kernel in IPython 0.14",
7 warnings.warn("IPython.lib.kernel moved to IPython.kernel.connect in IPython 0.14",
8 DeprecationWarning
8 DeprecationWarning
9 )
9 )
10
10
11 from IPython.kernel.util import *
11 from IPython.kernel.connect import *
12
12
General Comments 0
You need to be logged in to leave comments. Login now