It's time to look deep within the machine and understand what really happens when your Python code executes.
We're code walking through the CPython code base and visualizing it at pythontutor.com.
This is episode number 22 with Philip Guau, recorded Monday, August 3rd, 2015.
Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the
ecosystem, and the personalities.
This is your host, Michael Kennedy.
Follow me on Twitter where I'm @mkennedy, and keep up with the show and listen to past
episodes at talkpython.fm.
Be sure to follow the show on Twitter where it's at talkpython.
This episode is brought to you by Hired and CodeChip.
Thank them both for supporting the show on Twitter via at HiredHQ and at CodeChip.
Now let me introduce Philip.
Philip Guau is an assistant professor of computer science at the University of Rochester in New York.
He researches human-computer interactions with a focus on user interfaces for online learning.
He's especially interested in studying how to better train software engineers and data scientists.
He created a free web-based visualization tool for learning programming called Online Python Tutor
at pythontutor.com, which has been used by over 1.2 million people in over 165 countries to visualize over 11 million pieces of code.
Philip, welcome to the show.
My pleasure.
Yeah, it's really exciting to have you here.
We're going to talk a lot about many things.
We're going to talk about CPython and a really cool project that you put on your website and on YouTube called CPython, a 10-hour code walk.
And so we'll be digging into CPython.
And we're also going to talk about this thing called Python Tutor at pythontutor.com that you are working to help people understand the internals of Python better.
So that's going to be great stuff.
Cool.
I'm looking forward to it.
Yeah.
Before we get into the details, though, you know, everyone likes to know how people got into programming and how they got started in Python.
What's your story?
So my story was I was always interested in computers as a kid, like many people who got into computer science.
But I never really had a strong programming background until I went to college.
So I tried to learn QBasic by myself when I was 10.
And that, you know, I had a book and then I failed after a few weeks because I had no one teaching me.
I took an AP computer science course in high school.
That was in C++.
And that was really fun.
And that was kind of my first introduction to really doing programming.
And in college, I decided to major in electrical engineering and computer science.
And that's when I started just learning programming formally.
But really, the Python relevance is I didn't actually start hacking for fun until my about my senior year of college.
And the first language that I learned for programming for fun and not just because I had to do it for class was actually Python.
So the first kinds of programs I wrote were scripts to manage my photos and, you know, kind of manipulate and manage my own personal photo gallery and, you know, put it up on a simple website.
So that was where I got started getting hooked on Python.
That was, you know, it was about 10 years ago.
That was around 2005.
That was like Python 2.4 or something like that.
Yeah, that's a great way to get started.
I think a lot of people have interesting stories like that, you know, just they have some small problem they're trying to solve.
And, you know, it leads you down this path.
And all of a sudden, you discover this world where, hey, there's this great thing, you know, programming or Python or whatever.
Yep, that's exactly right.
So I see you're calling in from Seattle, right?
What are you doing up there?
So I am currently an assistant professor of computer science at the University of Rochester in upstate New York.
So that's nowhere near Seattle.
That's what I was going to say.
You're not – it's not at all in Seattle.
So I get to – one of the real benefits of being a professor is that your summers are free to do research or to travel or to do other sorts of scholarly work.
So most professors in most terms, they stay on campus in the summers and they do research full time for three months.
What I decided to do this summer since I had some colleagues at Microsoft was to spend most of my summer at Microsoft Research doing research and both in software engineering and in online education at the lab in Seattle.
And I came here because I actually was an intern here a long time ago when I was back in grad school.
So I'm actually back interning in the same group.
So it's sort of a homecoming of sorts.
Back to the future.
That's excellent.
Yeah, I've done some work with some of the guys up at Microsoft.
It's a cool place up there.
So excellent.
Is this related to PythonTutor.com?
No, not really.
I mean, this is just a completely separate sort of research project.
So there's nothing Python related in the work here, unfortunately.
All right.
Cool.
All right.
So let's talk about your CPython internals class.
This was a class you did at University of Rochester, right?
2014, I think.
At least the recorded version was 2014.
Yep.
So this was a class I taught in fall 2014.
And the name of the course was Dynamic Languages and Software Development.
So I actually inherited this course from another professor who was taking a leave and teaching another class that term.
And that class was originally in Ruby.
So it was sort of a graduate level programming languages class about these sorts of dynamically type languages.
And originally he did it in Ruby.
But since I knew Python a lot better, I revamped the class to be in Python and basically turned it into what the videos are online.
So I'd be happy to talk about that in detail.
Just for everyone listening, the videos are online.
And I actually spent like the last week going through your class.
So I feel like I've had like some super intense summer course or something, you know, doing like 10 lectures.
And people can find those on your website at pgbovine.net slash cpython dash internals dot htm.
And I actually went through, unrelated to this conversation or maybe preceding this whole having you on the show, I just saw your videos and thought they were awesome.
And I put them into a YouTube playlist at bit.ly slash cpython walk.
So both of those work well.
What was the main goal of the class?
Sort of get people to understand what happens when you actually run dynamic code like Python?
Yeah, I think that was basically that was basically a philosophy.
So a lot of programming languages classes are taught from more of a theoretical perspective.
Right.
So it's usually kind of some formal syntax and semantics and maybe doing some proofs.
And it's very, you know, kind of a formalism heavy.
And I thought it would be interesting to do a very different sort of class for graduate students from the opposite side, which is something extremely applied to saying, you know, here is a here is a piece of Python code.
Let's start with hello world or a simple for loop or a simple function call.
And what actually happens throughout all the steps between that code being parsed and then the output appearing on your screen, let's say.
So I wanted to dive into the interpreter and show students how everything worked under the hood and how there's really, you know, by deconstructing, you can show that there's really no magic here.
There's just a lot of C code behind the scenes that keeps track of a lot of stuff.
And eventually your program runs.
So we don't do the parsing stage because I think parsing is fairly standard.
And that's covered by most kind of introductory compilers classes.
You write a grammar and parser generator and some code gives you a like an AST.
And then that gets walked to turn into some kind of bytecode.
So the class actually starts with assuming you have a bunch of Python bytecode.
How does the bytecode actually get interpreted step by step by the by the interpreter runtime system to do your your programs operations?
Yeah, that's really cool.
And I think, you know, if I think about how like C code runs and then my intuition about how that C code actually executes, if you understand a little bit about registers and memory addresses and pointers, your intuition more or less will carry the day.
I think with interpreted languages, all bets are off.
Right.
I mean, you have some concept of the programming language doing things, but then the way that happens, you really have to look inside.
Right.
Yeah, exactly.
Because the these interpret languages are often not implemented like you would conceptually think of it.
Right.
You think of something as you have frames and variables and pointers to each other.
But really, these bytecodes are this sort of the Python one is sort of this stack based kind of virtual machine.
I think Java, the Java virtual machine is that way, too, but I forgot the exact semantics.
But it's not something you would think about normally, but they do it that way.
One, because it's really compact and it's kind of leads to really compact code and sort of easy to understand code for the implementer.
But yeah, but that's very different than the conceptual model in your head at the very high level, how a program ought to work.
And we can talk about that later when we talk about the Python tutor as well, because that kind of leads into that other tool.
So we can keep talking about the CPython stuff first.
Sure. So one of the things I thought was interesting was in your very first session, you did you have kind of a cool whiteboarding thing you're doing with a Microsoft Surface and like a pen where you can kind of draw on the code.
And that's cool.
You do a cool little sketch about what actually happens when you type Python space some file that py.
And I mean, on one level, I knew it.
On the other, it was a little surprising to me to say.
And the first step is compilation.
Can you maybe like talk just briefly about like what happens when I run my Python code before we get into the interpreter itself?
Yeah.
So many people are surprised when there's a compilation step in Python or in these sorts of dynamic or what people call scripting languages, because usually you think of running Python space, whatever, or Perl space, whatever, Ruby space, whatever.
And it just runs, right?
Right.
I just thought, here we go with the interpreter.
And now it's interpreting, right?
Right.
So with Java or C or C#, you have a compilation step and then you run a compiled binary.
And there's two separate steps.
But with Python, as with many other languages, the compilation happens before the execution.
So what happens is as a standard kind of a front end to a compiler, it takes the source code.
It does the lexical analysis.
It does the parsing.
It creates a AST or abstract syntax tree from that.
And then it walks that tree and creates a bunch of bytecode.
So the Python bytecode language, you can read in the documentation, it has, I don't know, a few dozen operations like add, load, store, and also some operations that are a little bit more Python specific, like build a list, build a dictionary, build a tuple, function call, those sorts of things.
So the compilation step really takes your source code, which is in human readable, somewhat human readable form, and turns it into a linear stream of instructions.
Very much like assembly language, except you can think of bytecode as an assembly language for a Python virtual computer.
Right. That was kind of the impression I got as well, like a much, much richer assembly language where you have operations like build class and call method, push and pop stuff off stacks and so on.
Yep, exactly.
If we want to go work with this, right, we can go to python.org and download the code and decompress it or untar it or whatever.
And it's just, it literally is a bunch of C code, right?
The C in CPython is, here's your C implementation of this interpreter, right?
That's right.
So if you go to, this is what I do on the first day of class.
We have everybody download the C interpreter source code from, sorry, the CPython source code from python.org and unzip it and do configure and make.
Now, part of the class, I didn't require students to actually run the interpreter if they didn't want,
because most of the class was actually reading through the code and walking through it.
Now, the students who were a bit more adventurous, they could try to compile the interpreter themselves.
And then try to, you know, put in debug statements or print statements to see how it works behind the scenes.
But actually, compile interpreter itself might not be easy if you're on, say, especially, say, on a Windows machine, which doesn't have a lot of development tools, compilers.
So I'm usually on Linux and Mac machines.
If you install the standard developer tool chain with GCC and make and configure and all that stuff.
In theory, right, building is always hard.
But in theory, if you do dot slash configure and then and you type make all your your you'll actually call the C compiler on your machine.
And it will compile all the C files and the C and the H files in the CPython slash directory.
And in the end, it will produce a binary executable file called Python.
And that Python you can just run.
And that is the Python interpreter that you just compiled from C source code.
So most of the class, what we do is we go over what a lot of those C files actually do and see.
Maybe you could give us like a 10,000 foot view of what are the interesting parts of that source code and what is just noise and details.
So there's like objects and then there's include there's see eval dot C.
There's there's like a few really common parts that you come back to over and over and over.
And then there's a bunch of details.
Yeah.
So on the Web site with all the videos, I actually show the the files that they reference.
But really, the core file that I keep on going back to what you're saying is in Python slash C eval dot C.
And what that is that that file at its core is the main interpreter loop.
So conceptually, how you execute how Python executes code is a byte code is just a bunch of them.
It's just a list of instructions.
Each one is add or subtract or build list or function call or so forth.
And all the interpreter does is just go through one instruction at a time, take it off the list of instructions, do something and then move to the next instruction, do something, move the instruction and then do something else.
And it might jump around the stream of instructions if you have, say, a function call or a loop.
But really, the main interpreter loop in C eval dot C, all it does is it's just a big, wild, true, infinite loop that just.
Yeah, there's like a huge switch statement.
And it is huge, right?
That's right.
Yeah, there's like a 3000 or whatever line switch statement.
There's a fun fact in there.
If you actually I don't know if it's in all the versions, but at least in some of the versions I saw, there's some kind of comment in there saying that they needed to like break up the switch statement in some weird way.
Because some C compilers just can't take switch statements that are that big.
So they had to actually break up the code into pieces because, you know, it wouldn't compile on some kind of computers because that code was just too giant.
Yeah, that's pretty funny.
It's like a 3000 line switch statement.
It's pretty cool.
But those are more or less the steps that have all the opcodes.
And so if I look at Python, it's not necessarily mapping one to one the Python code I write to these opcodes, which is a good thing for Python programmers, right?
That means you're working in a high level language.
You're not working like down in the detail, right?
But it also means it's hard for me to understand if I write, you know, create a class and I say, you know, T equals new test class.
What does that actually mean?
Like, how do I line that up?
And so you had a cool way to disassemble that, right?
And look at it.
Currently, candidates receive five or more offers in just the first week and there are no obligations ever.
Sounds pretty awesome, doesn't it?
Well, did I mention there's a signing bonus?
Everyone who accepts a job from Hired gets a $2,000 signing bonus.
And as Talk Python listeners, it gets way sweeter.
Use the link Hired.com slash Talk Python to me and Hired will double the signing bonus to $4,000.
Opportunity's knocking.
Visit Hired.com slash Talk Python to me and answer the call.
Right, right.
So the disassembler actually comes in the standard Python library.
So if you do, right, so if you do Python space dash M space DIS, which runs the disk module space, the Python file name, name of Python file, I'll actually run the main function in the DIS module.
And what that will do is I'll actually print out a somewhat human readable representation of the bytecode.
And the cool thing about that is that it shows the line number of which line of your Python source code compiles into which bytecode.
And as you mentioned, it's not a one-to-one mapping.
So one line usually compiles to several bytecodes because the bytecode is at a lower level.
So you can run that DIS command.
And the DIS module, you can just search for, if you search on your favorite search engine for Python space DIS, you should see the documentation for this disassembler module.
And that is in the standard library, and that gives you all of the stuff.
So now that said, though, that only prints out the instructions.
There was somebody who made a library called byteplay, which is B-Y-T-E-P-L-A-Y.
And that library actually is an enhanced version of the disassembler that lets you get the disassembled bytecode into objects.
You can actually play with it yourself.
You can manipulate it.
You can, you know, take it apart.
You can analyze it.
So this byteplay library, I haven't used it myself personally, but I know people who really like playing with it.
Yeah, that's cool.
A little more powerful.
One thing about the DIS module is it's super easy to look at just sort of flat code in Python files.
But if I want to look at the functions or I've got nested functions and classes, it's a little more work to do that, right?
Yeah.
So the default with the DIS module is it just disassembles the top level of your program.
So all the top level says is that if you define a function, it'll just say function definition.
And then what you have to do is you actually have to go inside that function and disassemble that function itself.
So it is a little bit more hairy.
And I don't know if byteplay handles all that out of the box, but it might.
But the idea is that the DIS module, if you just run it by default, it will just disassemble the top level program.
And any functions will not be disassembled automatically.
You have to actually grab the code of those functions and go in there and call dis on that.
So it is a little bit more tricky to do that.
Sure.
The other thing I thought was interesting is if I've got a function, let's say foo, in Python, I could say, what is it?
Foo.func underscore bytecode.
How do I – the bytecode is actually there on the function.
And you can look at it in its encoded form, which is kind of some binary string type thing.
And then you can also disassemble that as well, right?
That's right.
And that's what I think we're just leading into that.
So the idea is that DIS itself, if you just run it, it disassembles the bytecode of the, I guess, of the top level file.
But each function itself has its own code.
And like you said, I think it's – it's actually different in Python 2 and 3, the name of it.
But I think in one version it's like the function object dot func underscore code.
The other one is just like just dot code or something like that.
But the idea is that the code of the function just appears inside of it as a binary string of data.
So if you actually print it out, it just looks like some garbled string.
But if you run it through some – you can run it through some pretty printing function or through DIS.
And it actually shows you the bytecode of the function.
Because all a function object is that it's some context plus an actual string of bytecode that represents what the instructions are that the function is supposed to execute when you run it.
Yeah, the other thing I thought was pretty cool is – or interesting to understand is that sort of compile step that you talk about, right?
When I run Python My Python file, I get first like a compile step to bytecode and then the dynamic interpreted execution.
But all those functions and stuff, that bytecode is there and ready to roll.
It's just not kind of wired together until it gets to the interpreter, right?
That's right.
So you can actually compile – I think it's just the Python interpreter does the compiling and running all at the same time.
But I think there's actually a mode in Python that you can just compile to – you can just compile the bytecode and not actually run it yet.
I'm not sure exactly which flags are that one.
But sometimes people actually ship pre-compiled Python bytecode instead of the source code.
So there's – I don't know what reason people do this because you can just run the source code.
And some people like to obfuscate their bytecode maybe, but I don't know how well that actually works because you can kind of reverse engineer it.
But yeah, so the compile step is completely separate from the running step.
And like you said, once you compile, it's just a bunch of – instead of a text file, a .py file, it's called, I think, a .pyo file or something.
It's just a bunch of garbled stuff.
And then that garbled stuff, you can just run through the interpreter and it'll do your – it'll run with your program.
Yeah, it's really interesting to see how it's all coming together.
What do you think some of the main reasons for studying Python at this level are?
Like how does it make you a better programmer, do you think?
That's a great question.
I think that studying Python at this level of the implementation level, it kind of makes you – I feel like it makes you a better programmer in that you kind of, one, build a really good mental model of what goes on behind the scenes.
And you see that these languages are just tools made by people.
I think there's something really powerful in that.
I feel this is a very kind of systems perspective of programming.
So one analogy is that why do people study, say, operating systems or study compilers?
That's a good example.
Like the kind of classic thing in college is that a lot of people have to take an operating systems course where they build a very simple sort of OS kernel in C and maybe some assembly.
And their kernel kind of runs and it does a simple hello world.
Or you do a compilers course where you build a compiler using some basic building blocks.
And the idea there is that it's not that you're going to ever build an operating system or a compiler in real life or a new programming language.
You're not – most people are not going to implement a new kind of programming language.
But by studying the principles behind how it works, I feel like – I think it makes you a better programmer in that you kind of understand how large complex code bases are organized and logically broken down.
So I view this class like you've seen with these videos as more of like a code reading or literature exercise in a way.
Because we're actually reading through dozens of – actually not that many.
Maybe a dozen really core complex files and seeing how they – the pieces fit together.
So it's sort of like dissecting, you know, kind of a large piece of code.
I think that's really interesting in its own right.
Yeah.
A lot of people when they're in school at least studying this stuff, it's all very – I don't know, like you said, abstract or maybe not – it's not quite what I'm looking for.
But like it doesn't have the nitty-gritty details of the real world applied to it.
So all the error conditions that are so bizarre and all the optimizations, you don't necessarily have to deal with that.
And so when you do finally get to a real world complex code base, it's super hard to feel comfortable.
And I think, you know, you kind of helped your students do that a lot in there.
So that was cool.
Yeah.
I think that's – and like you mentioned, there's always a tradeoff, right?
So even in my choice of what to cover in this class, if you notice, I only cover maybe a dozen or so files.
I mean, the Python code base has hundreds or thousands of source code files.
And obviously, I don't have – one, I don't have time to cover all that.
And two, I feel like this dozen is really the conceptual core of the interpreter.
A lot of the files are just modules, right?
A lot of the files are just like here's how strings are implemented.
Here's how, you know, the socket class is implemented.
Here's how, you know, memory mapped iOS is implemented.
Those are all, I feel, auxiliary things.
But whereas the core thing is, you know, what is an object?
What is, you know, a class?
What is a function?
What is the interpreter?
So – and even as you notice from watching the videos, I don't go over every single line in excruciating detail.
I basically gloss over things and say, look, this block happens if there's some kind of error.
You run out of memory.
So, you know, look at that in spare time.
Exactly.
But here's like conceptually what happens.
So, it is a balance of, you know, exposing students to the nitty-gritty, like you said, but also not too nitty-gritty because there's so much complexity in the code that isn't core to the lessons in the class.
So, it's a balance.
Yeah.
A lot of times as programmers, we are – to be effective, we have to kind of zoom in, look at the tree, zoom out, look at the forest, zoom back in on another tree, zoom back in.
And that skill of like in and out is pretty awesome.
We talked about the opcodes.
That's one – and that eval C – cEval.c function or class where it has the main eval loop running around and around.
That's one of the main architectural pieces of CPython.
Another one was – that struck me was everything is this type of C object called pi object.
Yep.
Everything is a pi object, right?
Pretty much.
So, numbers, strings, custom classes, those all kind of make sense.
But even the class definition itself, functions, methods.
So, that was really interesting to me.
And then we have derivatives of those, like things that have pi object kind of as their base class, like pi int object for int, pi list object for lists, and so on.
But C is not an object-oriented language.
So, how does that work?
Right.
So, like you mentioned, the pi object structure, I guess, in C is the base of how everything is implemented.
All the objects are implemented in Python.
And what that contains is – that contains actually really few sorts of basic data.
And I think the most basic, I'm trying to remember off the top of my head, is one is a reference count of how many pointers are pointing to this object at once.
And it's because Python implements garbage collection by doing reference counting.
So, if you have nobody pointing to you, then you get garbage collected and your memory gets reclaimed.
So, everything is conceptually a subclass of pi objects.
So, if you want to make an integer object, it's a pi in object.
Or if you want to make a string, it's a pi string object.
If you want to make a function object, it's a pi function object.
And like you mentioned, C is not object-oriented language.
So, there's no inheritance in the language.
But really, you can fake it by basically doing what's called structural inheritance or structural subtyping.
What that really does is it's a hack where you basically create a struct that is – where the first few elements of the struct are exactly the same as the base class.
So, basically, the pi in object – I don't have the code in front of me.
But the pi in object, the first whatever –
What is it?
Type?
Like the class, the original type, and then the ref count like you're saying, right?
That's right.
So, those are the – yeah, those are the two things in pi object.
That's right.
So, there's a pointer to the – a tag saying what type it is.
And then there's the number of references.
So, every struct that represents some kind of a Python class – all the names are getting mixed up – starts with those two things.
And the cool thing there is because if you have C code that expects a pi object star, a pi object pointer, and operates on it, it knows that the first thing it accesses in memory is the type.
And the second thing, I think, is the reference count.
So, all of your code will work perfectly fine if it's an in object or a long object or a string object if the function you're passing it into expects just a base class of pi objects.
So, basically, conceptually, it's just subclassing or subtyping.
But that's how it ends up being implemented in C.
And, actually, how C++ does subtyping, I think, in its most basic form, is basically that.
Because C++ is meant to be compiled to be somewhat backwards compatible with C.
So, this idea of piling another class on top of another one structurally with the fields in the same places is a pretty classic technique.
Yeah.
You kind of – yeah, absolutely.
You kind of have to really understand C pointers pretty well to get it.
But once you do, it's pretty straightforward, right?
Because when you say pointer and you dereference that pointer and you say a name, that really just maps to, like, an offset from the base address.
And long as they all have the same shape up to that point in terms of in memory, you basically have inheritance, right?
That's cool.
This episode is brought to you by CodeShip.
CodeShip has launched organizations, create teams, set permissions for specific team members, and improve collaboration in your continuous delivery workflow.
Maintain centralized control over your organization's projects and teams with CodeShip's new organizations plan.
And as Talk Python listeners, you can save 20% off any premium plan for the next three months.
Just use the code TALKPython, all caps, no spaces.
Check them out at CodeShip.com and tell them thanks for supporting the show on Twitter where they're at CodeShip.
Yep, exactly.
And that's another kind of a side effect of studying this sort of – studying implementation.
Because most implementations are usually in C.
So you get to kind of see these interesting C tricks and see how other languages are built on top of that, like object-in-order programming.
Yeah, it's cool.
I definitely have a better appreciation for macros after spending 10 hours looking through that idea.
Because I did a lot of C++, but not a lot of pure C.
So, you know, some of the tricks you might do differently in C++, you know, almost, you know, have really nice macro solutions.
So that's cool.
Your other project, Python Tutor at PythonTutor.com, what's the relationship to this?
I mean, certainly PythonTutor.com helps you understand that sort of in-memory what's happening inside your Python code.
So I kind of see these things as somewhat related, these two projects that you had.
Maybe you could just introduce Python Tutor for everyone and then we could talk a bit about it.
Sure.
So Python Tutor at PythonTutor.com is a – it's a web-based tool where you can write Python code.
And actually now you can write code in a lot of other languages.
So you can write code.
It supports Python, Java, JavaScript, TypeScript, which is a Microsoft version of JavaScript with types, which works really well.
And also Ruby now.
What you do is you write code in your browser and then you run it.
And it actually goes – it sends your code to a server to run in a sandbox.
So it actually runs a real version of the language and not some kind of JavaScript-y simulation of it.
So it runs the code.
It sends back the execution trace, which is everything that happened when your code ran.
You know, what it did at every step, when it printed out, what variables there are, what data structures there are.
And then it produces a visualization for you that you can step through.
So it produces a visualization of every step of the code execution.
And then you can use a slider to go through it and see that, you know, the variables being created, the function stack frames being created, the pointers that are pointing to each other.
And what that lets you do is that lets beginners especially build up a mental model of what is kind of going on inside their program.
Because even for code – for experienced programmers, we actually build up this model ourselves.
We look at a piece of Python code and we think in our heads, oh, there's a variable here that's pointing something else here and that's pointing this other thing here.
And then we call a function and that function points to the same thing we do.
But those structures are really hard for beginners to build up in their heads.
And this tool has just been really helpful for a lot of people to build up that model.
And the relationship between that and the CPython stuff is actually really interesting because the CPython stuff is really for advanced learners who want to learn how things really work behind the scenes.
And like we mentioned earlier, the Python tutors, for most people, I think, it's more useful because it's really what happens.
It draws the pictures of what happens at the conceptual level, right?
That you're actually – conceptually, all you want to think about is you run every line of code and something happens.
You don't need to know about the bytecode or the stack or the main interpreter loop or PyObjects or everything.
So I think those two are really complementary.
One is for advanced kind of programmers who want to study internals, whereas the Python tutor is for beginners who are just learning the language.
Yeah, that's for sure.
I kind of saw it the same way.
I feel like there's sort of this understanding of the thing that is CPython.
And Python tutor is this great way to help beginners kind of form good mental models.
And your CPython walk is really good at actually showing a super deep understanding.
But they kind of give like two perspectives of the same thing.
So even though I've been doing Python for a long time and I know C really well or C++ anyway, I still thought that just looking at the stuff that was going on in Python tutor,
like it has some really great visualizations for showing basically like scope, variable scope and things like that, because that can be kind of hard to understand for beginners.
Those kinds of things, right?
Like because it's not just, well, it's in the curly braces.
And so when it leaves the curly braces, this variable is gone, right?
There's a whole different mechanism for finding what's defined where and so on.
Right.
That's right.
And also with the, with nested scopes and closures in Python, that gets even more tricky.
So the Python tutor has a way of visualizing kind of your parent frame.
So if you, for example, the classic case, if you define a function within a function, that inner function has access to the outer functions variables as well as the global variables.
And it gets even trickier when, you know, you have a function foo and inside of foo, you define bar and bar access is something within foo.
But then foo returns bar to its color and foo is the stack of foo is gone.
But when you call bar again, you can actually still get back to the variables that foo had, even though foo has finished executing.
And the Python tutor and these sorts of tools visualize that for you.
And it's been used by quite a few classes, especially I teach these things like nested functions and closures, which are not as obvious, you know, and they're, they're more advanced concepts.
Yeah.
I, I do professional like training for Python and other, other technologies as well.
And I was thinking I'd probably pull that up when it gets to the scope stuff for students, just, you know, because, you know, I'm teaching a lot of guys who have done C++ or .NET or something like that.
And just their mental model is not appropriate.
Right.
And just like seeing it is a lot easier than spending five minutes talking about it, writing some demos.
So I think that's really cool.
I think it can help, help a lot in those areas as well.
Yeah, definitely.
Please, please use it.
And, and, and let me know if you have issues.
I mean, it's pretty, it's pretty robust at this point.
I mean, the thing is, it does require an expert such as yourself to guide people through.
I mean, it's helpful for people by themselves.
But if you just, what people do as instructors, like yourself, is you just pull up a browser and start writing code and start running it and start explaining the code to the students one step at a time.
And that's a lot more useful, I think, than starting a terminal.
Right.
Because the alternative now is you start a terminal, write a, write a function or a nested function or whatever, and then put a bunch of print statements inside.
And then you just run the terminal and just print a bunch of stuff.
And you're like, okay, I got to explain why it's printing this.
But whereas in the Python tutor, it's printing it to the web terminal.
But then also every step you see, oh, it's printing this because X is now pointing to this.
And now X points to something else and it's printing that.
It's extremely clear.
Yeah, it is very clear.
And it's like, you know, if you were to do your terminal example and then go over to the whiteboard and sketch out what's really happening as you try to describe it, like Python tutor just does that drawing for you, right?
Exactly.
So the exact use case is what you said.
It really replaces a combination of a terminal.
It really replaces a text editor, you know, interpreted a terminal scene, like a REPL, and a separate whiteboard all in one.
And I thought it was really interesting you mentioned the .NET kind of the C slash .NET developers switching the mental model of Python.
A funny story about this is recently I wanted to learn Ruby.
I've always wanted to learn Ruby for a while.
I've never done it before.
And I felt a good way for me to learn Ruby is to actually write my own Ruby backend for the Python tutor.
So the Python tutor is actually, it's a very platform, it's a language independent interface.
If you notice the visualizations, nothing about the visualizations has Python.
They're just variables and stack frames and functions and lists and objects with attributes and stuff.
And you can imagine squinting and that makes sense in another language like JavaScript or Java or Ruby.
So what the backend does is that you actually write a backend, say in Ruby, by hooking into the Ruby debugger and printing out what happens at every step, you can actually generate visualizations for Ruby.
So I actually spent about two weeks really deep diving into the Ruby language implementation and debugger and how it works.
And I actually created the backend for Ruby, which is live on the site.
And that actually gave me some really interesting revelations about how scoping especially works in Ruby.
Have you done Ruby before?
I started to learn Ruby on Rails a little bit, played around with it, never really got very far with it.
Yeah, it's, it's, we could do a whole other podcast on that.
I think people who've done Python for a long time, when, when we learn Ruby, it just seems crazy and weird.
And I'm sure Ruby people say the same thing with Python.
The scoping is really weird.
So I have an example of Ruby scoping example is like something that really looks basic in Python.
Like, oh, this ought to work.
So I'll give you a, a classic example is if you have a, what looks like a global variable, like, you know, X equals five.
And then you define a function in Ruby inside that function, you cannot access the global variable.
Okay.
It's like insane.
And it's because it actually, when you define a global variable, it's actually not a global variable.
It's a local variable in that scope.
And when you define a function, I can like what it looks like a function.
That's actually a method on the default object, which is outside of the scope of your normal thing.
So it can't actually access what you think is a global.
So if you actually think of things in a Python way and you're doing Ruby, it gets super confusing in terms of scope.
So, but the Python tutor actually illustrates that all for you.
And it's like, oh, wow, I can see why I can't access that variable.
Even though I thought by looking at the code, I could.
Yeah.
And that way I think Python tutor is really interesting for experienced developers because we have these really strong mental models, but they're not always, they're not portable necessarily.
Right.
You can't just plug them into different situations.
And so seeing the differences might just quickly, you know, connect that, those two together.
Exactly.
And I think that's why I've been extending it to other languages because it's, I want this tool to be useful not only for someone who's an absolute beginner, who's never learned anything, but also for experienced programmers.
And one of the future pieces of work I love to get into, if I have time, is to kind of make the bridge between different languages.
Now that imagine Python tutor is this nice visualization that is pretty much language agnostic.
I want to see, like, one awesome thing would be, like, if I'm a Python programmer, I want to learn Ruby.
I want to write some Python examples and then see some equivalent or similar Ruby examples and step through their code and see, oh, this is how you do this, you know, do lambdas or do nested functions in Ruby.
It looks kind of like Python.
So I think that with this tool, because it's on the web, people can build up interactive examples showing how different languages differ from each other.
Yeah, I think that's actually really valuable.
Although you might need a 301 redirect to a language tutor or something like that, right?
Yeah, the name is funny.
Yeah, the name kind of stuck because it started with Python.
I debated a change of name for a while, and the domain is really good, and, you know, it's pretty highly ranked, and everybody, a lot of people know it.
So I think it might just be an inside joke.
I might just have to stick with Python for now, even though it supports these languages.
Yeah, yeah, of course.
It's cool.
So that's all really well and good for helping.
Before we move on, I guess, let me go back to one thing.
One other thing that I think is really helpful, even in this mode that we've already spoken about, we'll get to the other modes that we have available in Python tutor as well.
But one I thought was really cool is forwards and backwards execution.
Like, so I'm a huge fan of PyCharm, and PyCharm has really nice interactive debugging.
And, you know, speaking of Microsoft, you're around, you know, somewhere physically in here, the Visual Studio guys, and they have Python tools for Visual Studio, which have nice interactive debuggers.
But going back in a debugger is not the same thing as actually forward and reversing time.
And I think that's one of the things that's cool about Python tutor is I can run forwards.
Oh, wait, I didn't understand what happened.
Let me go back three steps, forward two steps.
You know, that's a really cool feature.
Yeah, and I think that's one of the key features.
And, you know, people have been trying to do reverse kind of debuggers in production for a while.
There are actually some teams, you know, doing stuff for various languages.
I mean, in production, it's really hard to do.
But actually, in this educational case, the forward and backward is sort of a trick because what happens is the whole program has already executed by the time you see it in the browser.
So when I'm scrubbing forward and backwards, I'm just looking at different pieces of the log that the program has already done.
So that's really nice because it allows you to go forward and backwards arbitrarily.
It's not like I have to re-execute it all.
The whole program is done.
I'm just seeing what did it do with step one and what did it do with step two and such.
That's awesome.
Yeah, there's not like an edit, continue, or drag execution pointer to skip this if check or something like that, right?
That would be cool.
But, yeah, yeah.
That would be cool.
But, yeah, it's a read-only view.
It's just it's done.
Yeah, this is the program you wrote.
Let's just see what happens at every step.
Yeah, I think that's amazing.
So the other thing that you can do that you seem to be building out more and more is to bring other perspectives into this.
So if I go around pythontutor.com and I go click some stuff, it's like an automated system showing me stuff.
But if I wanted to sit over the shoulder of somebody and help them understand it or if I was teaching a class and a bunch of people doing it, you've got tools for that as well, right?
Yeah.
So the immediate tool, it's all on the site right now.
If you look at if you go to the Python Tutor site, there's a start shared session button on the upper left.
And what that does is that it actually creates a unique URL that you can send to your friend or to a tutor or to a TA.
And when they join that URL, they actually get into your session.
So it's like you're both virtually in the same session that are sharing it.
So what you can do is you can write code together just like you're in Google Docs.
And then you can actually run when you run the code, your visualizations are synced up.
So you can actually when you step backward, the other person's screen also steps.
And then there's a chat box so you can talk to each other.
And you can also see each other's mouse cursor.
So that simulates the experience of, say, a tutor and a learner getting together and sitting side by side and trying to work out a piece of code together.
Except you can do this anywhere and remotely.
So we've deployed this for about a year now.
And a bunch of people, like hundreds of people, have just used the service to do both tutoring, like remotely, just saying, you know, I sent a link to my tutor and they can tutor me and I don't have to be in the same room with them.
And also people use it for collaborative learning, which is really neat.
So this chat room supports arbitrary numbers of users.
In reality, after you get to more than four or five, it gets confusing because so many people are trying to write code together and chat.
And it's just it's a storm of little mouse cursors.
Exactly.
So because you see everyone's cursor.
So I've seen people with three, four, maybe five people kind of talking about stuff.
So that's sort of the the tool that simulates a a kind of personal interaction with the visualization.
Then you have another form that is sort of almost a dashboard of many learners, right?
Right.
So then there's another tool that I've been building that isn't exactly live on the site yet because it's it's really a beta for tutors only.
And what that is, is that that solves the problem of there not being enough tutors.
So imagine if you're in a large, you know, in a real class, you know, in a college class, you might have 50 students in a computer lab and one tutor or TA there.
And what the TA has to do is run around the computer lab helping everybody.
And, you know, people are raising their hands or going around helping one person.
Then someone else raises their hand and go around helping another person in, say, an online course, you know, a MOOC or these massive online courses.
There may be a thousand students for every TA on the course.
And there's no way they can help everybody at once, obviously.
So what I've done is I built a dashboard that shows a tutor or a teacher in real time what a lot of students are doing at the same time on on a website like the Python tutor.
So this dashboard can show up to dozens of people and each person's actions are just in a little tile.
So it's like you have a you have dozens of little rectangular tiles and a big dashboard on your monitor.
And each one is updating in real time as the student is editing code or running code or seeing compiler errors.
So then as a teacher, you can glance and it's sort of like you're looking over the shoulders of, say, 20 or 30 students at once and seeing at a glance what they're doing.
And most of the time, students are just coding along or they're paused or they're thinking.
But then sometimes you see a student always keep getting the same compiler error or you see a student changing their code back and forth and seeming confused.
And in that case, you can start a chat with those students in directly in the tile.
So you can you can chat with any number of students you want.
And each chat shows up directly in their in their coding session.
And as a tutor, because you have this dashboard, you can simultaneously chat with many students at once.
And the reason this works really well in practice is because a lot of students are just paused or thinking so that you could jump in to help, say, three or four or five students at once.
And it's not like you're chatting all the time.
You're chatting, giving them a suggestion, giving them pointers or something.
And then they go off and do some work and you go help someone else.
And you can do all that from the comfort of your own of your own home without having to run around a giant computer lab.
Or if you're in an online course, you can't.
You don't know where the students are.
They're all over the world.
But you can just sit there in one central location and help up to dozens of people at once.
Yeah, that's really awesome.
So you've got all that in a blog post that's coming up pretty soon, right?
Do you know when that's coming out?
Yeah, so I'm writing up a blog post.
I don't exactly know what's coming out.
Hopefully, it'll be in the middle of the month.
I'm still kind of shopping around to different folks and seeing where I can get it published.
And the research papers on these projects are coming out soon on my website as well.
So all of these are kind of along the lines of my research projects, which all revolve around the theme of how do you build better interactive tools for teaching programming?
Yeah, awesome.
Speaking of interactive tools, we had Brad Miller on from Interactive Python.
And you guys are doing some work together as well, right?
They're doing something with pythontutor.com to integrate that?
Yeah, so Brad, Professor Brad Miller, he was one of the first users of the Python tutor back in the day.
So I started this project about five years ago as a graduate student.
And that had zero users.
And it was just something I did.
You know, like many hobby projects, like many of these open source projects, it just scratched my own itch.
I was teaching a bit of Python.
I wanted to create some visualizations that helped myself out.
And it was a fun thing to do.
I put this project online for about a year or two.
And no one really used it.
You know, I showed some friends and colleagues.
And I thought, oh, this is a kind of cool hobby project.
But then around 20, I think around 2011, oh, it was four years ago.
Around 2011, Brad was starting to build some digital textbook resources.
He had been an author.
He's been a professor for probably over a dozen years.
And he had written some Python textbooks.
And he was trying to experiment back then in 2011 with putting Python educational materials online in a digital format.
And, you know, because he's really innovative, what he wanted to do is he was thinking, I don't want to just put some text and code online.
Because then it's just like it's no better than reading a book except you're just on the computer.
I mean, it's better in the sense only in the sense that it's free, which is cool.
I mean, that's already great.
I mean, having a free digital textbook that's open source is great because many more people can read it.
But he's saying, you know, if we're all already on the computer, can't we do something more interactive?
So he found my Python Tutor project and actually challenged me to try to make it so that you can embed it within other web pages.
And theoretically, it was possible because it's just a web-based interface.
But, you know, I had to write a bunch of code to get it so that it can embed within other web pages.
And we did that.
This was four years ago.
And I've been working with him ever since on and off to embed the Python Tutor in his page.
So if you actually look at his interactivepython.org digital textbooks, throughout the textbook, you'll see little widgets here and there that show a piece of Python code with a slider through it.
And then you can just slide, and then the visualizations actually appear.
And then if you hit edit, you can actually edit the code in the Python Tutor and see the visualizations.
I think that's been tremendously helpful for students because they can not only read the code, they can actually see what's going on.
And the cool thing is that that all happens within the context of their normal interactive textbook.
So, yeah, so Brad is an early power user and longtime power user of the system.
So I'm glad you had him on the show.
Yeah, that's awesome.
And the students can even kind of, like, customize the code samples and save them and stuff, right?
So that's really neat.
Yeah, exactly.
And that's the cool thing about being online, that you can not only, say, with the Python 2, with the visualizations, you know, you can imagine someone making a visualization, right?
Like an instructor using PowerPoint to very carefully draw out pointers and lists and data structures.
And that's all good.
But then what if, as a student, you're like, wait, I want to change this code to make it go backwards or something?
And the cool thing about having a real tool is that you can just change your own code and see the new visualization instead of just seeing what the teacher imagined.
Yeah, that's wonderful.
Because that playing, that playful exploration is sort of key to becoming a good programmer, I think.
Exactly.
And that's something that's, you know, on a more philosophical level, that sort of tinkering mindset, like you said, is key.
I mean, on one hand, it's very important to understand fundamental principles like variables and scoping and function and stuff.
But a lot of this, you know, as you know, and I'm sure a lot of people have talked to, you know, software is really a craft, right?
You can't.
It's just like woodworking or, you know, being a carpenter or something.
Like you have to learn some of the basic physics and material science behind it.
But really, you can't just become an expert, you know, woodworker by just reading a bunch of books.
You have to start tinkering and making mistakes and, you know, bruising your hands.
And it's very similar.
You have to write a lot of code, play around, see a bunch of errors, and just build up this intuition about how things work behind the scenes.
And hopefully the visualizations help scaffold that learning.
Yeah, I think absolutely they do.
So very cool project.
I think, Philip, that might be a good place to kind of wrap it up.
Before I let you go, let me ask you two final questions I always ask the guests.
Great.
First of all, what's your favorite editor?
Oh, starting religious wars here.
I've used Vim.
Hey, there's no judgments passed.
No judgments passed.
So I started as an Emacs user in college for about a year or two.
But then I saw the light and switched over to Vim a few years ago.
So I've been using Vim for, I don't know, the past decade or so.
And I don't have any good reason for doing it beyond just muscle memory.
So I am not dogmatic about text headers.
I just think you should pick one that you work well in and just get really good at it, whatever it might be.
Yeah.
Learn the hot keys.
Really just become comfortable.
That's important.
So the other question is, there's a ton of stuff out on the Python package index.
You got any notable favorites out there?
Things people should know about?
I think that one of the really useful Python packages is more of a meta package.
So I think it's called this company called Enthought, which started as kind of a scientific Python company.
They make some packages.
There's one called Enthought Canopy.
And then there's another one.
I don't know which company does it, but it's called Anaconda.
I think it might be Continuum or Enthought.
But look up Canopy, C-A-N-O-P-Y, and Anaconda.
And those are really all-in-one meta packages for just installing 100 or so Python packages and a nice one-click installer that contain...
Mostly it's meant for scientific programming.
So it has things like the IPython notebook and NumPy, SciPy, Matplotlib, all the scientific packages.
But also just a lot of stuff for data science, for data processing analysis.
The reason why I suggest those is, especially for beginners, is because they have a one-click installer for Mac, Windows, and Linux, I think.
Because one of the annoying things about starting up with any kind of new language is just having to install extra packages.
So for people who are a bit more savvy, they can use PyPy, Easy Install, PIP, those things.
But sometimes they get annoying because you try to install it and it says, oh, some dependency is not found.
Or your operating system doesn't have this compiler and stuff.
Vars.bat not found.
Exactly.
Especially on Windows, right?
Especially on Windows, development is hard.
So the one-click installers, Canopy, Anaconda, they have a company backing them.
I think there's free versions.
And I just want to get past that headache and just get to the programming.
Yeah, especially if you're doing data science and you're doing it on Windows, I definitely second that.
Because it is super hard to get some of those things to compile over there.
Yeah.
And people have been talking in Python user groups and on keynotes at PyCon about how if you want to improve Python exposure, we need a better store on Windows.
Because the current store on Windows, it's pretty hard to get going.
But these one-click package installers are going to help.
And I'm hoping in the future, as web and cloud stuff get better, more of this stuff could be hosted in the cloud.
So imagine a web-based Python cloud service where the web IDs are so good.
I mean, I bet some companies are already starting to do this.
You can just have a web-based ID for Python, which is really responsive.
And all your stuff just runs in the cloud.
It has every single thousands of libraries available.
You don't even have to worry about installing.
You just import whatever you want and everything works.
I think that's the dream.
Yeah, that's definitely a cool dream.
There's a company called Python Anywhere on anywhere.com.
And they're started down that path.
It's not quite that far, but it is a pretty cool thing.
It's free for people to try.
That's pretty cool.
All right.
So, Philip, awesome conversation.
Thank you so much for being on the show.
Is there anything that you would like to talk about or tell people about that I forgot?
A final call to action?
Final call to action.
Wow, this is a high pressure here.
I think, I mean, I would say the call to action would be to find – actually, here's a good call to action.
A call to action is to go on YouTube and watch some of the videos that people have put up, especially talk.
So, PyCon, which is the main Python conference, has some great keynote talks or just amazing.
They're really good about putting up talks publicly.
I mean, they have hundreds of talks on all sorts of topics, and they're well-produced, too.
Like, PyCon and also the affiliates in different countries.
A lot of times what I do is I just listen in the background if I'm working or I'm doing errands.
Both the keynotes, which are more high-level, here's where Python is going, and also very detailed things.
Like, if I want to learn about networking in Python, I want to learn about data science in Python.
I think those videos are amazing.
There are so many of them.
I mean, it's just like thousands of them.
I totally second that.
That's a really good suggestion.
And on a more focused level for this conversation, I really recommend people go and watch your 10-hour code walk through the CPython code base.
You will absolutely learn something no matter what your experience level is.
It's very cool.
So, check that out.
Great.
Well, thank you very much for promoting that.
And I'm really glad I made this video.
So, I guess the final tidbit you want to include in the outtakes is that I didn't plan on producing those videos.
I mean, those are just part of my class.
And the great decision I made was I just turned on the screen recording capture.
And I have a Microsoft Surface tablet.
And that allows me to do a lot of the drawings and the more interactive things.
But really, what you're hearing is exactly what I gave in those, I think, 10 lectures or so.
That's exactly what the lectures were.
I did some light editing.
You know, in the beginning, you know, people were setting up in class.
And I did some light editing.
But if you notice, the audio quality isn't amazing.
That's the one downside because I didn't have a nice mic.
I just basically was teaching in front of the class.
But I feel like maybe another call to action is for people, if you're giving a lecture or giving a talk about something, just record it and put it online.
You know, the quality doesn't have to be amazing.
But just like the CPython walkthrough, it wasn't like I pre-planned to, like, go to a studio and, like, spend $10,000 making some high-quality production.
I just recorded this as part of my class.
And, you know, I set a disclaimer.
This is kind of rough.
You know, some parts are, you know, I'm stuttering or I'm kind of backtracking or there are mistakes.
But it's great to have the resources out there.
And something like Khan Academy, which is really famous now with Sal Khan, making these very simple sketches explaining basic math and arithmetic.
That's exactly how he started.
He just was tutoring his cousins.
And he had a pen tablet and he just recorded videos.
And he didn't care that they were kind of very impromptu.
In a way, people really liked that because it seemed really genuine.
It wasn't just some, you know, million-dollar production in a studio somewhere.
So I'm glad I put those up.
And the cool thing is I didn't actually take much work.
I just recorded it and did some light editing.
I probably won't do as much editing as you'll do on this podcast.
But, you know, and they're up and people happen to like them.
So I'm glad that I did that.
Yeah, I think it's a great contribution to the community.
So thanks for doing it and thanks for being on my show.
Great.
Thank you very much.
Yeah.
See you later.
This has been another episode of Talk Python to Me.
Today's guest was Philip Guau.
And this episode has been brought to you by Hired and CodeChip.
Thank you guys for supporting the show.
Hired wants to help you find your next big thing.
Visit Hired.com slash Talk Python to Me to get five or more offers with salary and equity
presented right up front and a special listener signing bonus of $4,000.
Check out CodeChip at CodeChip.com and thank them on Twitter via at CodeChip.
Don't forget the discount code for listeners.
It's easy.
Talk Python.
No caps.
No spaces.
You can find the link from today's show at talkpython.fm/episodes slash show slash
22.
And while you're there, be sure to subscribe to the show.
Open your favorite podcatcher and search for Python.
We should be right at the top.
You'll find the iTunes and direct RSS feed links in the footer of the website.
Our music is Developers, Developers, Developers by Corey Smith, who goes by Smix.
You should check out the entire song on our website at talkpython.com.
This is your host, Michael Kennedy.
Thanks again for listening.
Smix takes out of here.
Outro Music.