Have you ever been in a Python interactive REPL and said to yourself, "You know, this is nice and all, but... it's missing something. There's not enough me!" Well, worry no more! I'll show you how to do it in twenty lines or less! Let me introduce the main attraction:
Code
As unhelpful as that sounds, it's true. Python has a module in the standard library called Code
. You can check out the code module documentation if you don't believe me. The documentation is maybe a little tough to understand on first pass-through, so I thought I'd create a few examples to show it off. There are a few objects in the code
module, but only one that I'm going to talk about this time: interact
.
Interact
Let's dive in. I'll show you. Let's create a new file in our directory called shell.py
.
#!/usr/bin/env python
# I'll be using Python 3, for reference.
import code # seems silly, but works great
def custom_repl():
pie = "delicious"
pi = 3.14159
homonyms = (pie != pi)
code.interact(
banner="Hello! My name is Jeeves! I am fancy. 🎩",
local=locals(),
exitmsg="Ta-ta!"
)
if __name__ == "__main__":
custom_repl()
Try running it and watch the magic work.
$ python3 shell.py
Hello! My name is Jeeves! I am fancy. 🎩
>>> pi
3.1415
>>> pie
'delicious'
>>> homonyms
True
>>> 4 + 3
7
>>> import math
>>> math.sqrt(pi)
1.7724531023414978
<Ctrl-D>
Ta-ta!
As you can see, the banner message we specified shows, the exit message we specified shows (although it didn't work for me if I used the built-in exit()
or quit()
commands), and we had access to the local variables when interact
was called. And we can use anything to act as our local state! Go back in and create shell2.py
.
#!/usr/bin/env python
# shell2.py
import code
class Car:
def __init__(self, color, mileage):
self.color = color
self.mileage = mileage
def honk(self):
return "Beep!"
def __repr__(self):
return "<Car - color: {}, mileage: {}>".format(self.color, self.mileage)
if __name__ == "__main__":
c = Car("red", 20000)
code.interact(
banner="Now interactively inspecting {}".format(c),
local={"car": c},
)
Back in the shell... python3 shell2.py
Now interactively inspecting <Car - color: red, mileage: 20000>
>>> car
<Car - color: red, mileage: 20000>
>>> car.honk()
'Beep!'
Keep in mind that the local
parameter to interact
has to be a Dict -- such as the one returned by local()
and global()
.
Wrap Up
You can use this to provide a nice interactive aspect to your app to help you do shell things, inspect objects, debug, and much more. This is roughly how pdb works too! Django and Flask both use a variation on this for their "shell" commands too. I think I'm going to try to use it to generate an automated quiz or homework for a python intro class (similar to the swirl package in R). Have any other cool ways you've used this? Let me know!
Originally posted on my blog