Repository: ipython/ipython

Issue:
Pylab banner shows up with first cell to execute
If the notebook server is started with `--pylab=inline`, the first cell to be run shows the pylab banner ("Welcome to pylab...").



Discussion:
yes, that's been bugging me lately.  It's ugly, but we need to come up with a clean solution in general. The problem is that it's not really in the banner, it's a print statement made by the pylab code.  Since the first time stdout gets flushed is after the first execution, then we get it out at that point, which looks weird.  For example, if you open a qtconsole with `--existing` _before_ executing anything in the nb, then the console gets the printout and it doesn't show up on the nb.

So the first problem is: where pylab shows its backend info.  Since that code gets executed after the banner has been built and the shell initialized, it can't be part of the banner itself (which is built at construction time). In fact, `%pylab` can do that at any point later in the life of the kernel.  I don't see any sensible solution other than leaving it be as a print statement, since if it's done post-init, we do want to give feedback to the user.

The question then becomes, where do we show output that may have come from the kernel at startup?  I'm starting to think we need a little 'log area' that's very unobtrusive (perhaps even off by default) where this output is flushed.  Most of the time nobody needs to see that, and it's annoying to pollute the notebook area with initialization information all the time.  In my view, the notebook should only contain output from actions typed by the user in the notebook itself.

Perhaps for now we could just run an initial flush of the streams and store that output in a variable.  We can then offer a button (later menu entry or better UI element) for the user to see that output in a popup.  Most people will never even bother looking for it.

@minrk, do you know the init logic of the output streams well enough to run that flush at startup and grab any output that might be in stdout/err to get it out of the way?

ps - I'll make this high priority for 0.12 (but not blocker) in case we manage to get to it; it's really an ugly wart that takes away from the experience and I'd like to come out with a really clean and polished notebook out of the gate.

Fix is one line: add `sys.stdout.flush()` after the print statement in `pylabtools.pylab_activate`, and it won't show up in the notebook.

Or, to be a bit more general, a sys.stdout.flush() should be added to the very end of the startup process in IPKernelApp, so that any print statements made during startup have been sent prior to the first execution.

An alternative would be to add stderr/stdout.flush to the _beginning_ of the execute block, to prevent any lingering messages in the buffer from being associated with a later execution.  Under normal circumstances, this would be entirely superfluous after the very first call, which is the only point actually likely to have anything printed but not yet flushed.

@minrk: I actually agree with both approaches: things like pylab_activate should probably flush right away just to be safe, and we should also have a flush right at the end of the IPKernelApp startup, to hand off things in a clean state.  I can look into the code tomorrow, but if you have a minute just push those small changes up right away.  I'd rather not add flushing on every block execute at the start; since we do flush at the end, it's superfluous on all but the first.

It's actually a tiny bit more subtle than that, because it turns out the qtconsole receiving the pylab message _depended_ on this bug.  I'll do a PR with a first crack. It should still be tiny, but warrants a quick second opinion since there isn't one unambiguous right answer.

On Mon, Nov 21, 2011 at 10:51 AM, Min RK
reply@reply.github.com
wrote:

> It's actually a tiny bit more subtle than that, because it turns out the qtconsole receiving the pylab message _depended_ on this bug.  I'll do a PR with a first crack. It should still be tiny, but warrants a quick second opinion since there isn't one unambiguous right answer.

Great, thanks.  I'm busy lecturing today, but will look at it in the
evening if nobody beats me to it.


Resolving patch:
diff --git a/IPython/frontend/qt/base_frontend_mixin.py b/IPython/frontend/qt/base_frontend_mixin.py
--- a/IPython/frontend/qt/base_frontend_mixin.py
+++ b/IPython/frontend/qt/base_frontend_mixin.py
@@ -106,4 +106,9 @@ def _is_from_this_session(self, msg):
             from this frontend.
         """
         session = self._kernel_manager.session.session
-        return msg['parent_header']['session'] == session
+        parent = msg['parent_header']
+        if not parent:
+            # if the message has no parent, assume it is meant for all frontends
+            return True
+        else:
+            return parent.get('session') == session
diff --git a/IPython/lib/pylabtools.py b/IPython/lib/pylabtools.py
--- a/IPython/lib/pylabtools.py
+++ b/IPython/lib/pylabtools.py
@@ -19,6 +19,7 @@
 # Imports
 #-----------------------------------------------------------------------------
 
+import sys
 from io import BytesIO
 
 from IPython.utils.decorators import flag_calls
@@ -317,6 +318,8 @@ def pylab_activate(user_ns, gui=None, import_all=True, shell=None):
     print """
 Welcome to pylab, a matplotlib-based Python environment [backend: %s].
 For more information, type 'help(pylab)'.""" % backend
+    # flush stdout, just to be safe
+    sys.stdout.flush()
     
     return gui
 
diff --git a/IPython/zmq/kernelapp.py b/IPython/zmq/kernelapp.py
--- a/IPython/zmq/kernelapp.py
+++ b/IPython/zmq/kernelapp.py
@@ -287,6 +287,10 @@ def initialize(self, argv=None):
         self.write_connection_file()
         self.init_io()
         self.init_kernel()
+        # flush stdout/stderr, so that anything written to these streams during
+        # initialization do not get associated with the first execution request
+        sys.stdout.flush()
+        sys.stderr.flush()
 
     def start(self):
         self.heartbeat.start()


Test patch: