#!/usr/bin/env python # coding: utf-8 # # Multiple namespaces for IPython # #
# # # This is a simple proof-of-concept implementation of switching namespaces via magics. The key points we need: # # 1. IPython's namespace is stored on the `.user_ns` attribute on the IPython instance # 2. IPython relies on some globals in the user ns created with `ip.init_user_ns` # 3. A namespace in Python is a dict # # # First, we create a dict of namespaces by name on IPython, and save the initial value: # In[1]: ip = get_ipython() ip.namespaces = {} ip._original_user_ns = ip.user_ns # Next, we define a `%ns` line magic for switching namespaces by name: # # We use ChainMap so that globals that IPython defines, such as In, Out, etc. are available no matter what namespace we switch to: # In[2]: from collections import ChainMap def set_namespace(name): """Line magic for switching namespaces: %ns foo a = 5 %ns bar a = 10 %ns foo print(a) # 10 """ if name not in ip.namespaces: ip.namespaces[name] = ChainMap({}, ip._original_user_ns) ip.user_ns = ip.namespaces[name] ip.register_magic_function(set_namespace, magic_name='ns') set_namespace('default') # In[3]: get_ipython().run_line_magic('ns', 'foo') a = 5 get_ipython().run_line_magic('ns', 'bar') a = 10 get_ipython().run_line_magic('ns', 'foo') a # In[4]: ip.namespaces['foo']['a'] # In[5]: ip.namespaces['bar']['a'] # In[6]: get_ipython().run_line_magic('whos', '') # In[7]: get_ipython().run_line_magic('ns', 'bar') get_ipython().run_line_magic('whos', '') # We can also make a cell magic for running a whole cell in a given namespace, # then switching back to whatever was already active: # In[8]: def namespace_cell(name, cell): """Cell magic for running a single cell in a given namespace %%ns foo a = 5 """ save_ns = ip.user_ns set_namespace(name) try: ip.run_cell(cell) finally: ip.user_ns = save_ns ip.register_magic_function(namespace_cell, magic_kind='cell', magic_name='ns') # In[9]: get_ipython().run_cell_magic('ns', 'cellns', "\na = 'hello,'\nprint(a * 2)\n") # This didn't affect the running namespace: # In[10]: a # But we can recall the cell namespace: # In[11]: get_ipython().run_cell_magic('ns', 'cellns', 'a\n') # In[12]: for name, ns in ip.namespaces.items(): print(name, ns.get('a', 'undefined'))Feature request for @ProjectJupyter: Define multiple namespaces within the same notebook (without using functions).
— Juan Manuel Caicedo (@cavorite) May 5, 2016