From 2b8775524cab5ac7dd2c13a56d7f8c6809127ffa Mon Sep 17 00:00:00 2001 From: Evan Patterson Date: Mon, 9 May 2011 12:13:26 -0500 Subject: [PATCH] Properly support std* redirection when using pythonw on Windows. --- IPython/zmq/entry_point.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/IPython/zmq/entry_point.py b/IPython/zmq/entry_point.py index b8a47781716..47c3b4a33b8 100644 --- a/IPython/zmq/entry_point.py +++ b/IPython/zmq/entry_point.py @@ -52,6 +52,10 @@ def make_argument_parser(): help='set the REQ channel port [default: random]') parser.add_argument('--hb', type=int, metavar='PORT', default=0, help='set the heartbeat port [default: random]') + parser.add_argument('--no-stdout', action='store_true', + help='redirect stdout to the null device') + parser.add_argument('--no-stderr', action='store_true', + help='redirect stderr to the null device') if sys.platform == 'win32': parser.add_argument('--interrupt', type=int, metavar='HANDLE', @@ -72,13 +76,13 @@ def make_kernel(namespace, kernel_factory, """ Creates a kernel, redirects stdout/stderr, and installs a display hook and exception handler. """ - # If running under pythonw.exe, the interpreter will crash if more than 4KB - # of data is written to stdout or stderr. This is a bug that has been with - # Python for a very long time; see http://bugs.python.org/issue706263. - if sys.executable.endswith('pythonw.exe'): + # Re-direct stdout/stderr, if necessary. + if namespace.no_stdout or namespace.no_stderr: blackhole = file(os.devnull, 'w') - sys.stdout = sys.stderr = blackhole - sys.__stdout__ = sys.__stderr__ = blackhole + if namespace.no_stdout: + sys.stdout = sys.__stdout__ = blackhole + if namespace.no_stderr: + sys.stderr = sys.__stderr__ = blackhole # Install minimal exception handling sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor', @@ -233,10 +237,10 @@ def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0, interrupt_event = ParentPollerWindows.create_interrupt_event() arguments += [ '--interrupt', str(int(interrupt_event)) ] - # If using pythonw, stdin, stdout, and stderr are invalid. Popen will - # fail unless they are suitably redirected. We don't read from the - # pipes, but they must exist. - if executable.endswith('pythonw.exe'): + # If this process in running on pythonw, stdin, stdout, and stderr are + # invalid. Popen will fail unless they are suitably redirected. We don't + # read from the pipes, but they must exist. + if sys.executable.endswith('pythonw.exe'): redirect = True _stdin = PIPE if stdin is None else stdin _stdout = PIPE if stdout is None else stdout @@ -245,6 +249,19 @@ def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0, hb_port=0, redirect = False _stdin, _stdout, _stderr = stdin, stdout, stderr + # If the kernel is running on pythonw and stdout/stderr are not been + # re-directed, it will crash when more than 4KB of data is written to + # stdout or stderr. This is a bug that has been with Python for a very + # long time; see http://bugs.python.org/issue706263. + # A cleaner solution to this problem would be to pass os.devnull to + # Popen directly. Unfortunately, that does not work. + if executable.endswith('pythonw.exe'): + if stdout is None: + arguments.append('--no-stdout') + if stderr is None: + arguments.append('--no-stderr') + + # Launch the kernel process. if independent: proc = Popen(arguments, creationflags=512, # CREATE_NEW_PROCESS_GROUP