How to get Python interactive console in current namespace?

Question:

I would like to have my Python code start a Python interactive console (REPL) in the middle of running code using something like code.interact(). But the console that code.interact() starts doesn’t see the variables in the current namespace. How do I do something like:

mystring=”hello”

code.interact()

… and then in the interactive console that starts, I should be able to type mystring and get “hello”. Is this possible? Do I need to set the “local” argument of code.interact() to something? What would this be set to? How should it be called?

Asked By: user553702

||

Answers:

For debug I usually use this

from pdb import set_trace; set_trace()

it may help

Answered By: Facundo Casco

Try:

code.interact(local=locals())
Answered By: morsik

Another way is to start the debugger, and then run interact:

import pdb
pdb.set_trace()

Then from the debugger:

(Pdb) help interact
interact

        Start an interactive interpreter whose global namespace
        contains all the (global and local) names found in the current scope.
(Pdb) interact
*interactive*
>>>
Answered By: user1338062

For Python 3.10.0:

code.InteractiveConsole(locals=locals()).interact()

See the Python documentation for more details.

Answered By: Marc

How to mutate both globals() and locals() from code.interact

Unfortunately code.interact doesn’t let you pass both globals() and locals() from the current namespace unless you copy them into a single dict like code.interact(local={**globals(), **locals()}), but then changes you make to globals() and locals() won’t be persisted.

However you can work around this by subclassing the console and overriding its runcode method:

import code
try:
    import readline
except ImportError:
    pass

class MyInteractiveConsole(code.InteractiveConsole):
    """Extends InteractiveConsole to also pass globals to exec."""
    def __init__(self, globals, *args, **kwargs):
        code.InteractiveConsole.__init__(*args, **kwargs)
        self.globals = globals
    def runcode(self, code):
        try:
            exec(code, self.globals, self.locals)
        except SystemExit:
            raise
        except:
            self.showtraceback()

Having defined this somewhere, you can use it similarly to code.interact:

MyInteractiveConsole(globals(), locals()).interact()

Except that this will let you read and mutate both globals and locals:

  • x = 7 will set a local
  • global x; x = 7 will set a global

and when you leave the interactive console with Ctrl+D (or Ctrl+Z then Enter on Windows), the changes you made should persist in your globals() and locals().

Caveat: The docs for locals() warn:

The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

so don’t rely on these mutations to locals() for anything mission-critical. PEP 558 and PEP 667 go into more detail, and might make locals() behave more consistently in future versions of Python.

Answered By: John Mellor