Issue
I was playing around with namespaces in IPython (Spyder), and tried to see what happens if I dict.clear()
locals()
.
So, without further ado:
Python 3.8.5 (default, Aug 5 2020, 09:44:06) [MSC v.1916 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.
IPython 7.19.0 -- An enhanced Interactive Python.
In [1]: locals().clear()
In [2]: locals
Traceback (most recent call last):
File "<ipython-input-2-f1c14746c80d>", line 1, in <module>
locals
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 263, in __call__
self.update_user_ns(result)
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 201, in update_user_ns
if self.cache_size and result is not self.shell.user_ns['_oh']:
KeyError: '_oh'
In [3]: dict
Traceback (most recent call last):
File "<ipython-input-3-0d8c7dca5f1a>", line 1, in <module>
dict
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 263, in __call__
self.update_user_ns(result)
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 201, in update_user_ns
if self.cache_size and result is not self.shell.user_ns['_oh']:
KeyError: '_oh'
In [4]: globals
Traceback (most recent call last):
File "<ipython-input-6-0d1754e6861d>", line 1, in <module>
globals
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 263, in __call__
self.update_user_ns(result)
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 201, in update_user_ns
if self.cache_size and result is not self.shell.user_ns['_oh']:
KeyError: '_oh'
As builtins have separate namespaces, tried deleting local
:
In [5]: del locals
Traceback (most recent call last):
File "<ipython-input-5-61828b7e8872>", line 1, in <module>
del locals
NameError: name 'locals' is not defined
Expected, as the namespace itself got deleted.
I tried importing builtins
and assigning to __builtins__
In [6]: import builtins
In [7]: __builtins__ = builtins
In [8]: __builtins__.dict
Traceback (most recent call last):
File "<ipython-input-11-8211c7f1d719>", line 1, in <module>
__builtins__.dict
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 263, in __call__
self.update_user_ns(result)
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 201, in update_user_ns
if self.cache_size and result is not self.shell.user_ns['_oh']:
KeyError: '_oh'
At this point I noticed all the errors were attributed to _oh
. So I restarted the kernel, and checked locals:
locals()
Out[1]:
{'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['', 'locals()'],
'_oh': {},
'_dh': ['D:\\Programs\\Python\\StackOv'],
'In': ['', 'locals()'],
'Out': {},
'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x000002C2953F37F0>>,
'exit': <IPython.core.autocall.ZMQExitAutocall at 0x2c295420af0>,
'quit': <IPython.core.autocall.ZMQExitAutocall at 0x2c295420af0>,
'_': '',
'__': '',
'___': '',
'_i': '',
'_ii': '',
'_iii': '',
'_i1': 'locals()'}
So _oh
seems to be an empty dictionary. Now:
In [2]: locals().clear()
In [3]: dict
Traceback (most recent call last):
File "<ipython-input-3-0d8c7dca5f1a>", line 1, in <module>
dict
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 263, in __call__
self.update_user_ns(result)
File "C:\Users\sayan\Anaconda3\envs\tfgpu_py38\lib\site-packages\IPython\core\displayhook.py", line 201, in update_user_ns
if self.cache_size and result is not self.shell.user_ns['_oh']:
KeyError: '_oh'
In [4]: locals()['_oh'] = {}
In [5]: dict
Out[5]: dict
So I found how to get locals
back, but did not understand why assigning an empty dict
as _oh
brought back locals
.
But the same thing did not work in python IDLE:
Python 3.7.7 (default, May 7 2020, 21:25:33)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> locals().clear()
>>> locals()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'locals' is not defined
>>> dict
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'dict' is not defined
>>> import builtins
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: __import__ not found
>>> __builtin__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '__builtin__' is not defined
>>>
There's no _oh
and even the __import__
doesn't work.
- Question 1: If assignment (
__builtins__ = builtins
) worked, why couldn't I access builtins? - Question 2: What is
_oh
iniPython
and how does it help bring locals back, being an emptydict
itself. - Question 3: How to get
locals()
working in python IDLE afterlocals().clear()
(Without restarting the IDLE)
If Question 3 is too broad within the scope of this answer I can ask a separate question. Thank you.
NOTE: I tried IPython on Windows 10, and standard python prompt on linux (Ubuntu). Don't think this makes a difference, added it for the sake of completeness.
Solution
In a running ipython
session:
In [109]: id(Out)
Out[109]: 139634741914432
In [110]: id(_oh)
Out[110]: 139634741914432
_oh
is another name for the Out
dictionary, which we can use as:
In [112]: Out[109]
Out[112]: 139634741914432
In [113]: _oh[109]
Out[113]: 139634741914432
In [114]: _109
Out[114]: 139634741914432
So why they use another name, I don't know. In any case by locals().clear()
you wiped out that whole dictionary of variables you see in Out[1]
, and have effectively disabled the ipython
interactive session.
I don't know of any value to using locals.clear()
. It might 'safer' inside a function.
Magic %who
shows the interactive variables, the ones your own code has created. There may be a way of selectively deleting those, but I haven't needed it. If I need a clean ipython
session I just start one in a new shell tab or window.
I haven't used IDLE in a long time (don't even have it installed), so can't help with its locals()
. It has a much simpler history mechanism.
Looking at the magics, there's a %reset
that can be used to remove user defined variables, and even clear the In/Out
history. Read its docs.
See also %who_ls
and %reset_selective
.
Answered By - hpaulj
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.