Search code examples
pythonipythonread-eval-print-loop

How to configure IPython to execute cell blocks the same way as a plain Python REPL does?


Vanilla Python REPL:

>>> 'na'
'na'
>>> for i in range(4):
...     f'{_+_}'
... else:
...     'batman'
... 
'nana'
'nananana'
'nananananananana'
'nananananananananananananananana'
'batman'
>>> 

IPython REPL with same interpreter:

>>> 'na'
'na'
>>> for i in range(4): 
...     f'{_+_}' 
... else: 
...     'batman' 
...
>>> _
'na'

This difference is apparently related to the mode in which IPython compiles code, and unrelated to the display hook. Is it possible to configure IPython to compile/exec cell blocks as a plain Python REPL does? I'd prefer if IPython would not interfere or modify such underlying runtime machinery.


Solution

  • Set the InteractiveShell.ast_node_interactivity setting to 'all', either through the %config magic command:

    %config InteractiveShell.ast_node_interactivity='all'
    

    or in your ipython_config.py

    c.InteractiveShell.ast_node_interactivity = 'all'
    

    This will cause IPython to compile everything in 'single' mode, the mode that triggers sys.displayhook, instead of 'exec' mode, which doesn't use sys.displayhook.


    The possible settings for InteractiveShell.ast_node_interactivity are currently

    • 'all': compile everything in 'single' mode.
    • 'last': compile the last (simple or compound) statement of a cell in 'single' mode. Differs from 'all' in cases like

      In [7]: for i in range(5):
         ...:     i
         ...: for i in range(3):
         ...:     i
         ...:     
      Out[7]: 0
      Out[7]: 1
      Out[7]: 2
      

      'all' would have printed the values of i from both loops.

    • 'last_expr': compile the last statement of a cell in 'single' mode if that statement is an expression statement. This is IPython's default.

    • 'none': compile everything in 'exec' mode.

    • 'last_expr_or_assign': like 'last_expr', but does some additional AST transformation to print the value assigned if the last statement is an assignment statement:

      In [2]: xyz = "something else"
      Out[2]: "something else"