How to get Python interactive console in current namespace?
Asked Answered
K

5

17

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?

Kelle answered 23/8, 2011 at 18:2 Comment(1)
refs: digitalocean.com/community/tutorials/…Archi
C
29

Try:

code.interact(local=locals())
Can answered 23/8, 2011 at 18:9 Comment(2)
if you want the globals as well use the following: code.interact(local=dict(globals(), **locals()))Matz
any chance to feed the changes (from the console, like a=3232) back into the caller script?Creedon
D
4

For debug I usually use this

from pdb import set_trace; set_trace()

it may help

Decani answered 23/8, 2011 at 18:5 Comment(0)
C
2

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*
>>>
Custodial answered 23/5, 2020 at 6:52 Comment(0)
S
1

For Python 3.10.0:

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

See the Python documentation for more details.

Suribachi answered 30/3, 2022 at 22:10 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Tenaille
C
1

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__(self, *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.

Chargeable answered 9/6, 2023 at 0:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.