Consider the following snippet:
a = ''
def assign(letter):
global a
a = letter
If I load this in IDLE and run it (Python 2.7.6), it behaves as expected:
>>> a
''
>>> assign('b')
>>> a
'b'
But in the IPython built into the Canopy Editor (1.3.1) the global variable is not changed by the function:
In [2]: a
Out[2]: ''
In[3]: assign('b')
In[4]: a
Out[4]: ''
Is this expected behavior? How does one manipulate global variables in IPython?
For the record, I am aware of the dangers of global variables. I ran into this issue while trying to reproduce a caching routine discussed in a class: https://www.youtube.com/watch?v=OgPS2ziCEaw
1) IDLE is not using IPython so the comparison is beside the point.
2) The run
command in Canopy places a standard ipython %run
magic command where you can see it on the ipython command line in Canopy, and executes it.
3) What you report is the normal behavior of the ipython run magic command. It is a bit counter-intuitive on first encounter; the short explanation is that the global namespace of the module being run is different than the global namespace of the ipython interpreter. After you run a module, its namespace is copied into the interpreter's namespace (which is why a
is defined in the interpreter), but executing the function assign
(which was defined in the module and whose global command therefore refers to the module global namespace), alters a
in the module's namespace, not its copy in the interpreter namespace.
4) This might seem like unnecessarily confusing behavior, but the purpose is to make sure that modules that are run from the ipython prompt are run "clean" of whatever flotsam might be present in the interpreter namespace.
5) If you don't want this behavior, use %run -i mymodule.py
, which causes the module to run directly in the interpreter's global namespace. If you do this, your example acts the same as Idle. In Canopy, the easiest way to do this is to press up arrow in the python shell to recall the %run
command, then edit it to insert the -i
.
6) Commenter Padraic above says that he can't replicate it in ipython. The only explanations that I can see is that he has IPython configured to run by default in -i
mode, or that he is not actually running the OP's code snippet, but is instead executing those commands directly in the interpreter, thus using only the interpreter namespace.