Python is a wonderful programming language that is often underestimated because it's so clear and
simple. People mistake the simplicity for being too simple for real programs. After all, you didn't
even struggle to get your program to link against an incompatible static library or battle a DLL
version mismatch in your Python app at all today, did you? Usually we find the simple and clear
programming language to be powerful and fast. But what happens when it's not fast enough? Do you have
to stop and rewrite your code in C, C# or Java? Well, before you do something drastic,
Mike Mueller is here to teach us the techniques and steps to determine why our Python programs
might be slow and give us some tips to make them faster. This is Talk Python to Me, episode 66,
recorded Monday, July 4th.
Developers, developers, developers, developers, developers.
I'm a developer in many senses of the word because I make these applications, but I also use these
verbs to make this music. I construct it line by line, just like when I'm coding another software
design. In both cases, it's about design patterns. Anyone can get the job done. It's the execution
that matters. I have many interests. 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. Keep up with the show and listen to past episodes
at talkpython.fm and follow the show on Twitter via at Talk Python. This episode has been brought
to you by Rollbar and SnapCI. Hey everyone, it's great to be with you today. I have a couple of
news items for you this week. First up, Stitcher. If you've been listening to Talk Python to me on
Stitcher, I have some news for you. Unfortunately, due to some business practices that I believe are
harmful to the podcasting space in general, I've asked them to delete my listing and remove the show
from Stitcher. If you're unfamiliar with the service, it's basically a podcasting client. But instead of
just serving up my content from my servers like most players do, unmodified, Stitcher downloads my MP3
files, re-encodes them into a low bandwidth format, and then slices it apart and inserts their own audio
ads into my show without any form of revenue share whatsoever. I don't get a penny from them for this.
To me, this is unacceptable. I did a big write-up about it and you can find the link to the write-up
in the show notes. The article was entitled Stitcher and Talk Python Podcast, a farewell letter.
Next up, on a positive note, a review. I want to say thank you to Jamal Moyer who did an excellent
review of my WritePython at Code course called The Course Everyone New to Python Desperately Needs to
Take. It's an interesting view on what's good and what's not so good about my course. I gave Jamal access
because I was interested in his opinion. I didn't know he'd write a review, but I'm really glad he did.
Thank you, Jamal. You can find the link to his review in the show notes. Jamal actually has a
bunch of great Python content, so I encourage you to go check out his site. Now, let's hear from Mike
about making Python programs faster. Mike, welcome to the show. Hello. It's great to have you finally
on the show. I've seen a lot of your presentations and I've always thought that they were really great.
Today, we're going to take one of your PyCon 2016 presentations and sort of have a conversation
around it about making Python programs faster. Yeah. Very nice to have me on the show. I listen
to most of your podcasts. It's very, very interesting. It's an honor to be here.
Thanks so much. Thanks so much. Well, let's get started by sharing your story. How did you get
into programming in Python? I know you've been doing Python for a long time, right?
Yeah. Actually, I pretty much know. I started Python in 1999.
So I worked on my PhD thesis and the task was to couple numerical models. We had existing
numerical models. One was written in Fortran, one was written in C and I looked for a language
to couple. I knew I'm not going to write it in Fortran or C. I just want to have something
else. And I looked at different languages, Java and other things. And then I somehow hit Python
and I asked on a mailing list, would be a good language to couple things. And then I got a call
from Martin van Leeuwen. He's a German, he's a Python core developer now for quite a while.
And he just talked me into Python. And that's how I got started. So I used it for my PhD thesis
and coupled models. And I got into work, which was not really clear if this would work because
numerical models from different fields. And I put them together and made them work as one
model, as one program. And it worked out pretty well.
Oh, that's really cool. What was the subject of those models?
So actually, my background is hydrology. So I coupled a lake model, a groundwater model,
and a hydrogeochemical model. So you have this, after mining, you have, you do surface mining.
And then you take something out of the subsurface, which is the purpose of mining. And then you have
a void left. And this void typically fills with water, with groundwater and forms a lake. Now you have
this, what's called the pit lake. And the pit lake is pretty different than an actual lake in terms of
water quality. And that was the purpose to find out the water quality of this lake.
And there were hydrocarbular, this lake model, which kind of takes care of the lake itself.
And the groundwater model, which takes care of the groundwater part and the hydrochemistry,
which is pretty different from a lake model. Typic lake models are very different systems determined
by algae growth and stuff like this. And now this lake is different because you have these chemicals
going in there. Actually, you have a very acidic lake most of the time that depends on the
nature of this thing. So if you draw down the groundwater table, there are some kind of directions going on.
And they take things out of the subsurface and then the groundwater moves over the stuff into the lake.
And you have a very acidic system, which is very different than the natural system.
That's what I was working on. And for this one, I need a new model.
And I cuddled it and I did it with Python. And Python worked out very well for this.
Was it controversial or a big risk that you took to try to do this with Python?
No, I was pretty free. So in academia, just the end result counts. Nobody really was into programming.
All these people are experts in groundwater and lakes and stuff. But the programming part,
I was pretty much on my own and I could decide whatever I want. And nobody asked how I do it.
Just as long as it works, it works.
Yeah, that's cool. Yeah, I suppose probably the major alternatives were things like MATLAB or
not other programming languages necessarily.
Yeah, yes. I looked at different systems and first you have to get into this, how you're going to do
this. And then you say you can extend Python with C and then you can connect C to Fortran. And that's
how it did it actually. I wrote at this time, we didn't have tools yet. At least I wasn't aware of
this F2Py tool, which I use now regularly. It didn't exist yet. So I wrapped every single
subroutine in Fortran with C and then every single C function with Python by hand, which is a
very tedious undertaking.
I can't imagine, but you probably learned a lot doing it, right?
I learned a lot. I learned a lot. I learned a lot about the C API and I tried to keep it very simple,
which was still complicated enough because for every function, I had to study this,
how to do it and looked at some examples. And this time we didn't have stack overflow or anything
like this. You know, everything was just, if you email us, if best, and everything was much,
much slower than nowadays in terms of getting help on the internet.
Yeah, absolutely. Learning to program or learning the right techniques was completely different back
then, wasn't it?
Yeah.
Yeah, cool. So we're going to talk about making Python programs faster.
Yes.
Yeah. And you did a really great presentation at PyCon and we'll kind of go through the details
there. But in general, you know, how much does performance matter? Like on one hand, it might be
great to have faster code, but on the other, maybe we just get more VMs or pay a little more for our
cloud bill or something like this.
The answer is clear. It depends. It's very, very depends what you're going to do. For a lot of people,
Python is plenty fast. So I think for most cases, actually, Python is pretty fast. For most web
developers, I talk to them and they're pretty happy with it because most of the time the database or the
network or something, it's what causes the problem. Most of the time, Python is fast enough for this.
But I also teach a lot of scientists and engineers and depends what they're doing. If they just move data from A to B,
then Python might be fast enough. But if they do real simulations, then Python is way too slow for a lot of things.
So it depends very much what you're doing. And if they have the right case, then you need to do something to make Python
faster. That's one thing. But having a faster is always a good thing. Typically, faster is better than slower.
And sometimes it doesn't take a lot of effort to make things faster. That's one case.
So sometimes it's just making things a bit nicer and as a side effect, making it faster.
And the other thing is you put a lot of effort in to make it faster. So you make it actually more difficult to
understand, but you make it faster because you need it. I think these are two areas here.
Yeah, I think you're right. Certainly the computational stuff is really, really important. And I suppose with the
websites, it depends a little bit if you're a web developer on what is fast enough and how fast you have to be.
There was a really interesting study. I think it was by Amazon. It was something around like the price of latency.
And it said something like for
for every hundred milliseconds that our site is slower, we lose, you know, some percentage, like
several percent of business, maybe one, like something like one percent or something of business. And
you know, if you have a lot of traffic that also really matters, right?
Yeah. So performance matters. Just a question if Python is the one that that is a bottleneck for the
performance, it's not totally clear. There can be many other things that cause your site to be slow.
It doesn't have necessarily the programming language. There can be other considerations.
Absolutely. For example, if you've got a million records and you're doing a non-indexed query on your
database, it probably doesn't matter what language you're using.
Yeah.
All right. Cool. So let's talk about your tutorial. What was it called?
Yeah. It was faster Python programs, measure, don't guess. So you should to stress actually on the
measuring part. I started out actually in 2007. It was my first two tutorials at PyCon US in Dallas,
Texas, my first PyCon. And I gave two tutorials right away, which was amazing. And actually it was
a two part one. The first one was more or less what I have here, the measuring. And the second part was
actually extending Python with other languages, like C extensions and using other tools there.
And now it's just the first part. And this is stress actually in measuring, just getting a grip on your
system to find out what's going on and where are potential points to improve. I think it's very
important to have something to quantify what's going on and see where the problems are and then
maybe come up as a solution. And that's very important to measure things and to make it quantified.
You just have a gut feeling it's slow enough to do something that's not really going to work.
Yeah, I totally agree. When I started out doing professional programming, I did,
sort of scientific visualization tools. I found that lots of people, including my intuition,
was really quite wrong often about what was fast and what was slow. Maybe have like some really
complicated like wavelet algorithm. You think, oh, this has got to be just super slow and some other
place where you're just working with a basic data structure. And it turns out like the majority of
the time you're fiddling with the data structure or something like this, right? So this measurement
idea is really important.
Yeah, I can confirm that. I do it for quite a while and most of the time I have a kind of feeling
what's going on. But very often actually I'm wrong. So for some reason there's something else I didn't
think about it, which is very clear afterwards. You say, of course, that's the reason, but you didn't
think about it beforehand.
Yeah, and that's coming from somebody who spent a lot of time doing this optimization, right?
So even with the experience, sometimes it still can be hard.
Experience helps. It helps. It helps. But it's no guarantee that you get it right. So you have to
measure.
Right. And of course, you can look at code. You can say, well, I'm sure that this version of that code
is faster and this version of the code is slower. But if it's 10 microseconds versus 20 microseconds,
who cares? It really matters how you're using the code as well.
So one thing I thought was interesting when you talked about your PyCon tutorial was that
you said, we're going to use Python 3. And I've been on a big push to evangelize Python 3
and so on lately as well. And what was the reason you said it?
Yeah. So of course, I think you have Python 3 and you have legacy Python. So I would like
to use the current version of Python 3. I always, because I teach Python for a living, and I always
use Python 3 whenever possible. Because when you're outside in the real world, there's
still a lot of systems running 2.7. But still, I like to use Python 3 for teaching. And so
that's a nice way to do it. And if you want to do Python 2, then it's not that difficult
to write programs with the same source code that run with Python 2 and Python 3 if it just
takes a few steps. So it's all this deprecated stuff in Python 2. And you're mainly there.
It pulls from future prints, something like this. And then you are there. So most of the things
you can write. And that's why you are ready to run in Python 3. And you still have to
support Python 2 for some reason. And you still can do this. And that's very important, because
otherwise, you might redo a lot of work later on when you now kind of focus on Python 2.7,
even though all your colleagues are still on 2.7.
Yeah, absolutely. I agree with you. I think that's great. You know, from futures import, was it Python?
Sorry, print function. And then maybe, maybe range equals x range.
Those kind of things.
Those kinds of things. And then you can write your Python 3 code in a way that is compatible
with Python 2, long as you, the other way, you can get yourself more into trouble, I think.
Yeah.
Yeah, very interesting.
The PyData balloon, I just gave it a troll about writing code that runs with Python 2 and
3 at the same time. And actually, I think the best thing is use the Python future org library.
Maybe you're familiar with this. This gives you a lot of whatever you said, but on a much higher
level, there are a thousand tests on it. And instead of making your own kind of compatibility,
they just use this library and they take care of a lot of details, including rearranging the standard
library imports and stuff like this, which can be really useful. So you pretty much write Python 3 code
that also runs on Python 2. So in Python 3, nothing changes, but on Python 2, you get all this
compatibility stuff in there automatically, which is very nice. And I think it's a good solution.
Yeah, that's fantastic. And in 2020, coming up, there's going to be no more Python 2 support.
Yeah, yeah.
And that seems like that's way in the future. It seems like there could be a science fiction
show set in 2020, but that's like three and a half years away.
Yeah, I still remember 10 years ago, like yesterday, so it's not a long time.
Yeah, that's right. That's right. Let's dig into some of the topics of your tutorial.
You started out by saying there are some general guidelines for measuring and understanding
performance.
The first thing is, it's the execution. How fast is fast enough? So the customer says,
do I have a case in the first case? So do I need to do something? And that's a lot of things.
Just look at your system and say, do I need the performance? What am I going to do with it?
It's a one-way thing, and I'm going to throw away. It doesn't matter if it runs half an hour or one
hour if I throw it away. So if I spend another day improving it, just to be half an hour faster and
never use it. Like scientists write a lot of one-way just moving data from here to there or something.
That could be the case. Or the other, you have to have some realistic use cases. Is this really
too slow? What am I going to do with it? Those kind of questions. It seems very common sense,
but actually most of the things are common sense. You just need to think through. Do I have a case?
Do I need to improve it? And look through. And then again, as I said, if you're in a web
application, maybe it's a database. Check how fast the database is. The network connection is really
Python. Can you gain anything out of it? And how much can you potentially gain?
Sometimes you can say, okay, I can gain not more than 20% anyway. Is it worth the effort?
If you have to pay for the CPUs and you use a lot of CPU, maybe 20% is worth the effort.
If you just wait overnight and if it takes six hours or seven hours to calculate,
so scientific calculation can easily take as long. It doesn't really matter because it runs
overnight. It doesn't matter if it's finished in the morning. It's fine. Those kinds of things.
Those are very common things. So those things you need to maybe reiterate after a while,
then you do something if you have a case. That's the first thing.
Right. And then the next one you said was sort of the whole story around premature optimization.
Like don't optimize as you go. Write your code in the most understandable way
so that it works. And then think about performance, right?
Yeah. First make it right, then make it fast. That's very important.
Yeah. Yeah. And the make it fast part is all about the measurement. Yeah?
Yeah. The first thing that I've ever focused here on the measurement, how to measure.
There are several tools out here. I use most of the time C-profile, which comes with Python,
which is a good tool. The other tools now actually are the Intel is doing a big thing. I just have this
beta stage kind of profiler, which is probably quite a bit better because when you measure something,
you always influence your system. There's no way out of it. So the problem, the question is just how much
you influence the system. If it's 1%, it seems to be okay. If it's 100%, it doesn't sound very right.
Yeah? So the question is you don't know how much you influence the system most of the time.
And then you want to have some kind of profiler that doesn't interfere too much with your things,
especially if you measure time and things are very short, then the timing might be too coarse to give
you some reliable results.
Right. Or the overhead to time, very, very small function calls might be 10 times the cost of the
function calls themselves.
Yeah. And that's kind of tricky how to do this, how to measure this actually.
And you can't avoid this, right? This is sort of the Heisenberg uncertainty principle kind of like
it behaves in one way until you observe it, then it behaves in a different way.
So it seems really important to me to just look at the difference, to measure one version,
change your algorithm and measure it again, rather than try to just, you know,
poke at it and say, well, I ran this test and now this is slow, right?
This portion of Talk Python to Me has been brought to you by Rollbar. One of the frustrating things
about being a developer is dealing with errors, relying on users to report errors, digging through
log files, trying to debug issues, or a million alerts just flooding your inbox and ruining your day.
With Rollbar's full stack error monitoring, you'll get the context insights and control that you need
to find and fix bugs faster. It's easy to install. You can start tracking production errors and deployments
in eight minutes or even less. Rollbar works with all the major languages and frameworks,
including the Python one such as Django, Flask, Pyramid, as well as Ruby, JavaScript, Node,
iOS, and Android. You can integrate Rollbar into your existing workflow, send error alerts to Slack or
HipChat, or even automatically create issues in Jira, Pivotal Tracker, and a whole bunch more.
Rollbar has put together a special offer for Talk Python to Me listeners. Visit rollbar.com
slash talkpython to me, sign up, and get the bootstrap plan free for 90 days. That's 300,000
errors tracked all for free. But hey, just between you and me, I really hope you don't encounter that
many errors. Loved by developers at awesome companies like Heroku, Twilio, Kayak, Instacart,
Zendesk, Twitch, and more. Give Rollbar a try today. Go to rollbar.com slash talkpython to me.
Yeah, that's very, very important. To compare to something, okay, that's this version. This
version, the difference is very small, but this version is twice as long. Why do we spend so much
effort to make it just a little bit faster? Maybe it's not, it's not, it's much easier to understand
shorter version than a longer version. And again, 10% and just say how often is this called and what
does 10% mean for my whole application?
Right. Absolutely. You've gone through and you've measured it. Now you've decided, okay,
it's time to make it faster. And you had some really good advice that you probably shouldn't
start trying to make it faster before you have good test coverage, right?
Yeah. That's a big problem, especially with scientists. So even though science is supposed
to be reproducible, test coverage is not something that a lot of scientists use. You cannot generalize
this, but very often a lot of scientists, depends how much they program, they might not even use
version control in any way or something because they're not aware of it. Some people do for sure,
but some don't. And also they don't know what measuring means just run it and look at their
results and say, that's right. So when I say tests, you want to have automated tests or something
that you can reproduce later on. And that's a big problem in scientific community. Depends
where else some scientists do this, but some don't do it all. And then if you try to increase the
performance, you change your code. And when you change your code, you might change behavior and you
don't want to change the behavior. You want to have the same result at the end, but just a bit faster.
Yeah, absolutely. You don't want it to be really fast and wrong. That would be terrible.
Yeah. But I think testing scientific results can be super tricky, right? You change the algorithm and
you've got floating point cutoffs and different heuristics and it might still model the thing
correctly, but in a slightly different way. And so you can't just do like a old value, equal,
equal, new value sort of analysis, right?
You need some help. So you need to do something like NumPy provides a few helpers. NumPy is a package
used in scientific computing quite a bit. And they have, they have offers some helpers to compare
arrays with some tolerance. So you can say, I want to compare the tolerance can be X. So it doesn't have
to be exactly the same. There can be small variations, which is totally normal if you do numerical calculations
and you do a lot of, a lot of them, then there will be some small differences, those kinds of things.
There are some tools there that make the work easier.
Yeah. I think there's a couple of really interesting speed ups that you talked about.
And one of them, I'm sure it's obvious once you know about it, but depending on your background,
where you're coming from, maybe you just have no awareness or it's not on your mind in terms
of thinking about performance, but alternate interpreters or runtimes, right? Like under certain
circumstances, you might be able to switch your code from say CPython to PyPy and get pretty
serious performance improvements, right?
Yeah, that's true. So PyPy can be very nice, especially for numerical competitions for
loops. And when you write a for loop in pure Python and use only integer or floats in there,
typically PyPy can find this out and just make it faster. So it compiles it to machine code in the
background. And very often you get close to C speed. So somewhere the range of C speed, then writing the
same loop in C, which can be easily factor of 10 faster or even more than pure Python.
Yeah. So if you need a 20% speed up and you can get your code right on PyPy, maybe you're already done,
right?
Yeah. Yeah. Very likely you're done. PyPy, of course, they have this benchmark and I think it's a very
big benchmark and they factor 6.5 times faster. So that's way more than 20% for average benchmark.
I think they don't have a single one where they are slower, actually. The worst thing is we get the
same thing. So as soon as you have a problem, it's not going to work for something like Mercurial,
where the time is in starting the interactive program. So of course, PyPy, I think it's slow
on startup. It works for things that are computationally expensive and we repeat it many times. If you do
something only twice here and there, PyPy doesn't have any way to do it. It has to be done like 10,000
times and then PyPy says, okay, it's doing almost the same thing. I can compile this with the machine
code and then you can get a speed up, which is pretty close to C. Actually, they had this one contrived
example where PyPy was faster than C because PyPy managed to inline some function calls where C just
was steadily compiled and called some library functions. And PyPy was bit faster than C, which
is of course, it's pretty contrived, but still you can get close to C.
Yeah, it's really cool to see those examples though, that that's a possibility, right? And if you use it
in the right circumstances, it's very cool. Let's suppose we've decided that we need to make our code
faster. And just to keep the conversation a little bit simpler, let's say we'll stick to CPython for
for whatever reason. So you talked about a couple of tools that we can use to understand our code
and a variety of them. And the first thing you talked about was this thing called PyStone. What's that?
Yeah, PyStone is just a benchmark, a simple benchmark. And benchmarks are always
wrong in one case, in one way, because benchmarks are designed to measure some kind of performance.
But maybe they're better than us. PyStone comes with Python. So it comes with the Python standard
installation. And you can run PyStones and this gives you a feeling of, because it's pure Python,
Python. So it runs with CPython, with PyPy, with Jison, with IronPython, whatever you want to test it
with. And you can see how fast the Python installation is. And of course, it's also connected to your
hardware. But if you run it the same machine, then you get a PyStone. You can also have this
kilo PyStone. So something can, of course, get a big number, but also gives you a time.
The bigger the PyStone, the better or the shorter the time, of course. And you can see if you run this
over this PyStone, you can have a very rough comparison of different Python interpreters.
And of course, if you run on different hardfares, the hardware will be included in this thing.
Right. For example, if you're working on your dev machine, but then you have some big virtual machine
in the cloud that you're actually going to run your code on, you could say, well, if it's taking this long
here and I can compare the PyStones from my dev machine versus production, then you get like a
little bit of a sense for the scaling factor up or down, right?
Yeah. So it's very, so it's pretty controversial if PyStone is a good benchmark. So it's one of the
benchmarks. If you want to, you can take other benchmarks. You could go for the PyPy benchmark
and see how this works or other benchmarks around to run it. But it just gives, the thing is simple
because it's there. You don't have to go and make it work because it's supposed to work
with this part of the standard library. And as far as I know, it works with giant
sin. It works with iron Python. It works with PyPy. It works with CPython from the old to
Python 2 and Python 3 everything. So you can get a feeling how fast your Python is.
And then the next thing you talked about is using C profile to measure your code.
A bunch of profilers around. One of them is profile that's written in Python, which has a lot of
overhead. So it's not really recommended. And C profile is, as the name suggests, written in C.
So the overhead is much less.
But it only works on CPython, right? It won't work on something like PyPy, will it?
It works only on CPython. So I focus this on CPython because it's more about the principles
than about the tools. In particular, I would say just get people kind of a workflow how to do this.
And if you have a different setup, you might need to use a different system. Like if you work on
Json, you might use some profilers that job-up gives you or something. I'm not an expert in this field,
but the procedure is the same. So you want to measure. And my caution is always,
those tools can be wrong. Sometimes you get strange results and you always have to question it. But you
might find a second or third way to measure pretty much the same thing and see, look at the results
correspond somehow. If you get totally different results with different tools for the same
kind of measurement, then there must be something wrong with the tool or how you apply the tool.
Maybe you just use it in the wrong way.
Right. Or even there's some really crazy overhead like you're calling a function a million times,
but the measurement of it is so much larger that it's just completely out of whack, right?
Yeah.
Okay. And so if I had like some method and I wanted to profile this, what's the steps? Like,
what do I do with C profile to get this rolling?
So first I shows this slow way to do it just with the standard library. So it's just import C profile. You
have to make instance of a class profile, and then you have several abilities or possibilities
how to call the method. You just can put the method in these arguments. You can also use a string,
let's evaluate a string, and then as Python code and get the results. And then you get an object that
it represents the results and it calls different kinds of print or other evaluation methods on it.
And it shows you the results. The three profile only goes by function. So the finest resolution,
you see how much time it takes to run one function call. It shows you how many times a function being
called, how long it took per call, and how long it took in total. You have a lot of ways to sort this
by the most calls, the longest times. And you can also sort who called whom. So you can have a
relationship, this function called this function. So you get some kind of a graph there.
Yeah. Okay. Yeah. That's really nice. And then you also use Jupyter Notebooks to do some cool stuff
there. Yeah. So if you're mind it easier. So Jupyter Notebook is actually the killer application of
Python, I would say. Because of Jupyter Notebooks, they have what's called %PRUN, which is kind of a wrapper
around C profile. There's no new functionality in this case, but it makes it much more convenient. So instead of doing
doing three steps, importing, making instance, you just say P run. And P run takes some like
command line arguments. So you can specify how many times you want to repeat or whatever you want to do.
And then it runs your function call and gives you all the results in the same way, which is very nice.
So that's, if you use the Jupyter Notebook, used to be called IPyce Notebook, but nowadays it's Jupyter Notebook.
You should use it anyways. It comes from the scientific field and it's used a lot. So if you go to your
PsyPy or PsyPy conference, pretty much everybody's using Notebook. But it can be useful for everybody who's
programming a person just to try something out. And this profiling means to try something out, try something
again and again. So the Notebook is great for this. And this gives you pretty much everything you can do with
the C profile, just much shorter and much more convenient. And if things are shorter, then you're
more inclined to do something. So if it makes it more convenient to do something, then you will do it more
often and you measure more often, I would say.
Yeah, the easier you can make this and the more automated you can make it, the more people will
do it, right? And with Jupyter Notebooks, you can go back and you see the cells that you ran before
and you just kind of like rerun them again if you want to retry it. And yeah, it's really nice.
Yeah. And then of course you get a table output, but then you say, you know, a picture saves more
than a thousand words. There are some nice tools to actually visualize it. And I use this one called
SnakeWiz. So you just run SnakeWiz on the output. So the C profile, you can store all this profiling data
in a file. I think just Marshall, just put there. And then you read it back with SnakeWiz, for instance,
and it gives you a nice picture. So you can look in the browser and it's an interactive thing. So it's
running a, this file is interactive. So you can zoom in and look at different things. It gives you everything
in a nice colorful picture, which is really helpful because you can see in a part of a second what's
going on, what function takes most time. So you can look at it and then you can click it and you see,
have all the information. It's nothing different than the table. But if you have a big table with
a lot of numbers, it takes you a lot of time to make sense out of it. And this diagram you get there,
it's much more convenient to use.
Yeah. Certainly when you have tons of data, almost anything like having a really fantastic
way to slice and dice and visualize it makes all the difference. And this SnakeWiz is really cool. So
the way it works is basically you run the profiler and instead of printing out the stats to the terminal
or something, you save them to a binary file. And then this SnakeWiz can like suck that up and it runs a
little local web server that then opens your browser and you cruise around in there, right?
Yeah. Yeah. Yeah. It's very nice. And you have, you have the table and you can also sort the tables,
tables and there also, so you have the raw numbers if you want to, but you also have this picture and
they have two different ones. They have one is a circle, like the, the outermost function is innermost
circle and that's going outwards. And you see the circles getting smaller and smaller, like fractions of
a circle. It's very nice visualization. The other one is called icicles. So instead of a circle, you have squares
of areas that are, or not rectangles actually, stacked on top of each other, which also kind of symbolize this
function is calling this function. You see where the time goes.
Yeah. That's really cool. And I think, you know, if you have a program that you care about performance,
run this through it really quick and just look at the picture and you'll probably learn something right away.
The case is if you see one big function that uses all the time, then you know where to go.
If it's very evenly distributed among a lot of functions, then it's much harder because we're
going to start. You have to look at all these functions at the end. So that's, that's the first
thing. You see, you have a case. If you all the time is in this function, then it's very worthwhile to
look at its functions. If you have 20 functions, so they all take about 5% of the time. Yeah. We're
going to start. So it's, it will be much more works to work through all these functions.
Right. It's, it's not just low hanging fruit, but it's, it's something, it's something different.
Right. So that's CPU profiling. And one of the ways your code can be slow is it's just
computationally expensive, or you could also discover, I guess, external things that are slow.
It could be, you know, the cumulative time for like a disk IO or a database call or a web service call
could be really large. And that would tell you that that thing is slow. Right.
Yes. Yeah. Actually you can do it as a C profile. C profile typically measures wall clock time.
So the time that actually elapses from the beginning to the start, but you can also also provide your own
timing function and you could do something like CPU time. So CPU time is where the CPU spends doing
something. So if you have, if you use something like time sleep in your code, say time sleep,
two seconds, and the wall clock time will be two seconds, but the CPU time will be nearly zero because
the processor is not doing nothing actually just waiting for you to do this time sleep.
So this is very important to see. So if you do input output, you wouldn't see the wait for something to
that, that it happens in time sleep. Just let the processor rest in, in terms of your process,
of course, the processor is still working, but not for your process, not what you're measuring.
And that's an important thing. So that's what I try to get across that most of the time you measure
wall clock time. Unfortunately, that difference is between windows and Unix systems. What if you,
especially in Python 2, if you just use a time.time, which gives you a timestamp on Unix,
which is nice on windows, it's way too close to do anything useful. Therefore you should use time.it
default timer. So something I was like to get across because we very often, you see a lot of online
tutorials that use time time, which is totally fine on Unix. But if somebody, somebody is trying this in
Windows, you might not get useful results because it's pretty coarse. And also there's a time.clock, which is much faster
on Windows means measuring time on Windows, but measuring CPU times on Unix. So it's pretty, pretty messy
here. So you might mix things up. You measure, might measure the wrong thing depending on your platform, which is
not, it's not good. And therefore I give you like a small helper function that gives you also the CPU time on, on
Windows. That's completely not obvious that the time is evaluated difference and sometimes even means
something different on the different platforms. Yeah. Actually, I think it has a reason because it's
just a thin wrap around C library. The C library is different on the platform. In Python 3, it's better.
There's a time perth time, I think, which kind of attracts this away a little bit. So it's getting better.
There's another reason I use Python 3. So you have a better abstraction of this, platform abstraction of this measurement.
Continuous delivery isn't just a buzzword. It's a shift in productivity that will help your whole team become
more efficient. With SnapCI's continuous delivery tool, you can test, debug and deploy your code quickly and reliably.
Get your product in the hands of your users faster and deploy from just about anywhere at any time.
And did you know that ThoughtWorks literally wrote the book on continuous integration and continuous delivery?
Connect Snap to your GitHub repo and they'll build and run your first pipeline automagically.
Thanks SnapCI for sponsoring this episode by trying them for free at snap.ci/talkpython.
So that lets us measure things like web service calls and databases as well, which is really interesting.
But sometimes it's more of a memory pressure or a memory issue. Like maybe the reason our code is slow is because actually we're running out of memory and it's like going to page on memory on disk for the virtual swap files and all that kind of stuff. Right? So can we profile memory as well?
Profiling memory is not the simplest thing, but there are some tools out there. And I used to use Hippie, which is part of this GUPP project. But as far as I know, it's only Python 2 so far, if I'm not mistaken.
Profiling memory is not the same. But there's another project called Pimpler, which is also a merger of three different projects in the past, and this supports Python 3.
They do pretty much the same thing. And if you have the chance, actually, you can use both of them to compare the results with the Re, which is always good.
Profiling memory is also a Pimpler, which is always good.
So you can just use a Pimpler, which is always good for the Pimpler, which is always good for the Pimpler, which is always good.
Profiling memory is also a Pimpler, which is always good for the Pimpler, which is always good for the Pimpler, which is always good for the Pimpler, which is always good for the Pimpler.
And if you have a Pimpler, which is always good for the Pimpler, which is always good for the Pimpler, which is always good for the Pimpler.
So you can write your own tooling that is totally tuned to what you want to do.
So you have this basic tools and then Python makes it so easy to write some nice special tools for your use cases.
Yeah, that was really cool.
And I really liked the way that you're using decorators in your tutorial.
Like here you have one called like, you know, measure memory or something like that.
So you want to measure some function and all the functions it calls.
Of course, you just say at measurement memory in front of it.
Right. And then you get this little little summary, which is really cool.
Yeah. So I guess if you want to answer the question of how many bytes is this, you know, five or 10 byte thing I've created, like this wouldn't be the way to do it.
This is a way to get like large scale pictures of, oh, I have 10 million integers and I didn't expect that.
What's the problem, right?
Yeah.
But there's also ways to like actual get object size from this library, isn't there?
Like, yeah.
Yeah.
Difficult to know the full like closure of an object graph size, right?
Yeah.
You can use this, get a size of your, the system module and the sound library has a size of, which gives you the memory size of one object, but it's only the object itself.
Like you have a list, you get the size of the list, but you don't get the size of all the objects stored inside the list.
And the objects that they store and the objects that those objects store, right?
And so on.
Yeah.
Pimplot is giving you this so you can actually measure.
And actually I have a very nice example.
They're very interesting.
So I start with an empty list and then I keep appending to this list, one integer after the other, up to a million or 10 million actually.
And then every time I append, I measure the size of this object and see how it changes.
And use two different ways.
I use this kind of built-in, sys get size of, which gives you just the size of the list.
And then the other one from Pimplot that gives you the whole memory, the list and everything, or the integers in my case use up.
And you can see a very nice step function because that's how Python actually works.
So you have a list and Python always allocates a bit more, roughly 50.
There's a formula, but roughly 50% or so more memory.
It fills this memory.
And then when it hits the limit, it allocates more and more.
So if you have 10 million appends, I get like 104 or so allocations, which is, because allocations are pretty expensive in terms of time.
So this makes lists so efficient if you do append.
If you use some other structure that would need to be rebuilt, or if you use, instead of appending to a list, you insert zero.
You insert at the beginning of a list.
That means every time you do this, you have to rebuild the whole list and you have to allocate all the memory again, which is a big anti-pattern actually.
And it's very nice.
You can visualize this.
Why is it like this?
And you can see a picture.
And I think it always, if somebody tells you that's the case, it's one thing.
If you do it yourself and you measure yourself, it's a very big difference in terms of experience.
You see, okay, I measured myself and I can play around with it and see how things change.
Yeah.
I thought the graph was really cool because it made it very clear what the algorithm was.
You can see that it's basically trading a little bit of memory for a lot of performance.
Yeah.
In the general case, right?
In the general case.
Yeah.
And obviously you can buy memory.
So buy a bit more memory just cost you a few bucks, but make making a CPU a thousand times faster is pretty hard.
I would say.
Yeah, absolutely.
So the other thing that you showed in your tutorial that I thought was really cool that I don't think we've touched on yet is line by line measurements.
So you could do line by line CPU profiling as well as allocation management, right?
Yes.
You can do this.
So there's, there's a line profiler from Robert Cron.
So, as an author and actually he ported it to Python 3 now, because I asked him several times to do this.
And now the line profiler works with Python 3, which is, it gives you a lot of overhead.
So it makes your program much, much slower, but gives you a line by line breakdown because the C profile is just the smallest increment you get as a function.
And you can do a line by line profiling, which is especially important if you write a function and you have like calls to NumPy.
So in a function, you might have three, four, five calls to NumPy.
Then you can see which call takes the most time, for instance.
Right.
And this is what the line by line profiling is doing.
Yeah.
So maybe you, you see profile and, and those sorts of techniques to go and figure out, all right, well, I know it's really this function that is a problem, but it's, it's 10 or, you know, hopefully not a thousand.
It's 10 lines long.
What's actually slow about that, right?
Then you can turn on this line profiler business.
Yeah.
Exactly.
Because you only want to have one or two functions.
You use a decorator, add profile, you know, you put a decorator called profile there, and then you run it through your profile with some options.
It is this line profiler, and then it makes it very, very slow.
So either maybe factor of a hundred slow or something like this.
It feels very slow because it just has to go line by line and check everything what's, what's doing and gives you a nice breakdown.
You see, okay, allocating this list or this number is array takes so much time and then looping over it takes so much time and doing this takes so much time.
So you could see pretty much where the time goes, which is, can be a way to be useful educational.
So you can get a feeling what these functions are doing, but also useful to make your program faster.
You also talked about some anti patterns, things that you should try to avoid or, you know.
Yeah.
Can you go through a couple of those?
Yeah.
One is I just said is about maybe the most important one is about the list.
So if you have a list, then you want to append at the end.
And maybe when you, when you're done, you just reverse the list.
If you want the other way around, instead of inserting at the position zero, which is what you want.
And this would be big anti pattern.
And this can be many orders of magnitude difference in terms of performance.
If you do this one, and this is one of the biggest anti patterns.
And now the anti patterns is like string concatenation, which is an old one, which it's now kind of optimized in CPython.
So instead of saying string plus equals new string, string plus equals new string in a loop, you just use a list and append to the list.
Take advantage of this list behavior.
And then at the end, you just join the list.
Yeah.
Because the list do this pre allocation thing where strings don't.
Yeah.
So this is actually, it's not really true anymore.
It used to be the beginning of Python.
So I started with Python 1.5 too.
This was my first Python version.
And it was pretty true, I think.
And then pretty soon they changed, they optimized it away.
And it works with CPython.
But if you use PyPy, which is supposed to be much faster, then this anti pattern just kicks you.
Then if you do this for a string of like say 100,000 characters, it just kills the performance.
And you have to wait an hour or so instead of a second.
Wow.
Yeah.
I don't really, I remember, I just read it somewhere.
There's a reason that it didn't put it in this optimization.
So you never know if CPython always can optimize it.
Because for simple cases that I use string literals and stuff like this, it should be easy.
If it maybe is a code a bit more complex, who knows if it's still up to an optimization.
So it's better not to rely on this.
As long as the string is short, it's fine.
But it gets a bit longer than...
Yeah.
Yeah, it's a problem.
Maybe you're streaming stuff out of a CSV file and trying to build up a thing.
And maybe it can no longer optimize that.
Who knows, right?
Yeah.
Who knows?
Another interesting example you had was looking, sort of optimizing variable and function
lookups.
Like caching global things like square root versus math.square root, for example, in a function.
Those kind of things.
So it depends what you're doing.
It can be, it can give you a little bit speed up.
So because that's just the basic thing how Python looks up names.
So first looks in local namespace in your function, then goes to the global namespace, which is your module, and then goes to the built-in namespace.
And every lookup is kind of a dictionary lookup.
And instead of going like this global, even the built-in namespace, like if you use sum, the built-in sum, then every time you use sum,
Python has to go and hunt for sum until it finds it.
And so if you say, okay, my sum equals sum in a function, for instance, then you make it a local variable, and you avoid like two lookups for every time you use sum.
This can be useful.
Yeah, if that's in a tight loop, then maybe that becomes a problem, right?
Or a loop within a loop.
So if it's a tight loop, you don't do much else, that might be something.
If you do a lot of other heavy computations, or the sum itself takes a long time to sum something big, then you still get the speed up from the lookup avoidance.
But percentage-wise, it might be just half a percent faster.
It might not make a lot of difference.
If you don't do much else, you can get several 10% faster behavior or something like this.
So it depends very much on your use case, but at least you can try, and this would be one thing.
So if you call a function or some built-in or global variable in the inner loop again and again and again, making it local might speed up things a bit.
Sure.
You had a cool example where one of the points you were making was saying, look, sometimes it's an algorithm, and you just need to look, you know, not optimize a function a little bit, but you need to rethink how you're doing something.
And you had this created, it was a contrived example that was computational, but you were basically computing pi using the Monte Carlo method.
And you said the naive way to do this would be to sort of generate a couple of random numbers, do some math, save some values, and do this in a loop.
And you said, well, look, if we do this with a different algorithm like using NumPy, we get dramatically different performance, right?
Yeah.
So NumPy, the algorithm with the Monte Carlo algorithm is maybe the worst algorithm to calculate pi.
There are much better algorithms out there than give you pi with 100 digits with 100 iterations or so.
So in Monte Carlo, 100 iterations would take the age of the universe to calculate, I guess.
So it's computationally, but it makes a good example because it's very slow and you can use a lot of techniques to improve it because also it's embarrassing parallel.
So I use it later on, actually, to do some parallel calculations with multiprocessing and other means.
So it's a very good example because I use the same example with many different kind of approaches, which is useful.
So it is simple enough to understand.
So I use this and then you just run it in normal Python.
And as I said, one of the things where Python is slow is when you use numerical computations and you use 4x in range, 4y in range loops, something like this.
This is pretty slow.
And if you just use NumPy and NumPy is doing this vectorize, so instead of writing a loop, then you vector, you just call the function in NumPy.
The fact that when you program NumPy, you should pretty much never write a loop.
You should always vectorize things if you want to make it fast.
And then NumPy just runs us with a function which is running in C, when you get near C speed for a lot of things.
So it makes it much faster.
Yeah, yeah.
That was really cool.
I like that example.
What if people missed this, right?
This was actually done in June.
So if they weren't there, they've already missed it.
There's a couple of opportunities to still check out your presentation though, right?
Yeah, the presentation does, you can go to YouTube.
If you go to PyVideo, it's on YouTube.
If you search for it, you will find it.
So if you go to the PyCon US site, then it should be there.
So if you look for faster bicycle.
Yeah, and I'll link to it in the show notes as well.
Yeah, you can link to it.
And also I will give this tutorial again at Europython in just in a few weeks in Bilbao,
in Spain.
So then there will be this tutorial again.
So I will talk about it.
Yeah, Europython is going to be very exciting.
That'll be a good conference.
Yeah, it's a nice conference.
I gave it last year there.
So it seems like because there's always demand for it and people like it.
So it's just because it's, I try to always make it hands on so you can follow everything.
So there's nothing.
It's too sophisticated, which is on purpose.
Because if you show too sophisticated code, people won't understand.
So everything is pretty simple and you can use it right away.
And hopefully when you understand, you can apply it to your own use case.
That's the whole purpose of the thing.
Yeah, that's great.
So we just have a few minutes left in the show.
Before we call it quits, let's talk a little bit about what else you have going on in the Python space.
I've been in the Python space for quite a while, since 1999.
Actually, I spent my most, actually my professional life in the Python space.
I teach Python.
So I'm the founder of Python Academy, which is now more than 10 years old, actually.
And that's where I teach Python.
I gave my first Python course in 2004.
It's quite a while ago.
So I taught university level courses in different fields, but in scientific fields.
So I had some experience in teaching and gave a lot of talks at conferences.
And it was just a small step to Python courses.
So just how it developed.
I really like teaching.
It seems like it fits.
So people understand most of the time what I'm saying.
And so I started teaching Python.
And meanwhile, Python Academy grew.
Now we have about 11 teachers.
So not everybody's teaching all the time, but I have a lot of different teachers doing web development,
testing, Sison, database programming, and have also teachers that have different native languages.
So I myself can teach in German, which is my native, and in English.
But I also have people teaching in Italian and Polish and maybe in other language later on.
So some people might be taught in their own native language, which might help to understand.
Yeah, absolutely.
And congratulations on the success there.
That's awesome.
I've been deeply involved in training and training companies for the last 10 years myself.
And I know what it takes to put those together and keep them running.
Yeah.
It's a lot of effort.
So I myself, Python Academy, we focus on everything Python.
So very wide range in terms of Python, but deep in there.
So I teach beginners, people that barely programmed before, or other programmers,
so professional programmers that wanted to switch to Python, but also advanced Python.
I have advanced Python course, but that's a Python track.
I also teach scientific tools, which is a very wide field.
So I teach how to use an IPython on Jupyter Notebook and NumPy and some SciPy tools and Matplotlib and Pandas,
those kind of things, which is in very high demand in terms, because scientists need these tools all day long.
Yeah, absolutely.
What's your favorite one to teach?
It depends.
So I like to have variations.
I like the scientific thing.
And actually, but I typically like in a course, I like to include examples from the people and actually do a little bit of live programming in the course.
So they have a problem and say, okay, I need to, scientists are often to have to read in this file A and have to convert it into file B, which is a very common thing.
And Python really shines in this.
So you can actually in the course ad hoc, develop a smaller routine and read in the file.
There's different tools.
So you can do it.
It's just standard library.
You can use Pandas, which is great for CSV files and something like this.
And then you say, okay, now I have this file and I've assigned the data and then I write it back somewhere.
And this is very often very useful because then I can use a lot of things I taught in the course.
So how to do this, how to write a function, how to write a doc string in a function and how to make a function, refactor the function because it's getting too big.
Everything, but on a small scale, so understandable for people.
And I see it's really useful if you do this.
So you can reuse this function again and again, do something.
That's mainly for scientists that very often scientists use programming as a tool, but they're not so deep into programming very often.
As compared to professional programmers, for them, there's nothing new.
They pretty much understand when I say something, they understand the concept and that's pretty easy.
You can go on.
For scientists, you have to give an example because just explaining it in this very kind of generic examples might not be kind of really good enough to understand what is useful, can be useful for.
Right, because they spend most of their time working on physics or biology or something real, right?
Yeah, something real.
So it depends.
Some of them tend to become programmers.
Very often scientists turn programmers.
But many of them just use Python from time to time as a tool, as an important tool.
And as soon as they get their result, they just forget about it and go on.
Then I said, wait a minute, you can, now, the script works, but if you spend another half an hour, you can make it reusable.
And next time you can save a lot of time because you put this in a function and you put a dong string.
Maybe you put a test in there.
So make it work.
And it makes it much more useful.
Even your colleague might be useful.
Now, if you write this small function or several functions that can read this file format, then your colleague can use it.
If you just have a script that's doing everything in one piece, then your colleague is probably not really able to use it without a lot of efforts.
Right.
You end up starting from scratch every single time.
Yeah.
So it's kind of, it depends.
Yeah.
So that's what I like.
I like the variety.
So I like introductory courses, even though I taught it many times, but also like the advanced course.
And lately I had a course where people really used meta classes.
And I had to really dig deep into meta classes.
There were some very hard meta class questions.
I had to kind of think really hard because meta classes, but as a topic, most of the time, if you don't know what they're doing, you don't need them.
And then you could stop the course.
But sometimes they can be useful for certain types of things.
And these people will use them to a high extent, which is interesting.
Pretty challenging course though.
Yeah.
Cool.
Yeah.
It's great to have that spectrum.
Do you also do consulting?
So actually I do some scientific consulting.
I just help some develop some lake model.
So we do some consulting in scientific area.
Of course not only me, so we have a team of a few people.
So we also do consulting and program something.
And sometimes you also connect to consulting actually pretty frequently.
So develop a solution, but instead of handing over a black box solution, we do a workshop with it.
So we explain how things work and how people can extend what we did.
So you get a really solid solution, which is people probably like scientists would not be able to write themselves, but they can build on it.
So they have this basics.
This is a good foundation.
You can build it and you can use it and increase it and make it more useful for their needs.
Yeah, that's great.
That's really helpful.
And then finally, you've done a lot with conferences.
You were involved with EuroSciPy, EuroPython, and so on, right?
So it seems like I'm pretty much into conferences.
So actually, I started pretty much, I was the guy behind pushing EuroSciPy.
So I started here in Leipzig where I'm located.
And 2008 and 2009, the first two EuroSciPys happened here and I was a chair.
And now EuroSciPy has a great success.
Then we had two conferences in Paris, two conferences in Brussels, two in Cambridge.
And now we're back to Germany in Erlang and it will be in August, so just a bit more than a month from now.
That will be the number nine EuroSciPy.
So it seems like a success.
People come to EuroSciPy and it's continuing.
So I've been involved in EuroSciPy.
And also I'm involved in PyConDE.
So 2011, 2012, PyConDE.
The German PyCon was here in Leipzig and I was a chair.
And also, of course, PyConDE is run by the Python Software Verband, which is a kind of a German Python Software Association.
And I happened to be the chair there also.
So I'm a bit involved in community work.
And then we also did EuroPython 2014 in Berlin and I was also the chair, which was a big conference, more than 1,200 people.
Yeah, that must have been a lot of work to put that together.
Yeah, so we had a very great team.
So, of course, you have the chair.
You just kind of oversee everything and try to delegate as much as possible, which is necessary because it's just impossible to do main or bother work yourself.
You have to have a great team.
And we had a lot of people that are very enthusiastic about it and put a lot of effort in there.
And it was a great conference.
I had a lot of good feedback from people about the conference.
Yeah, cool.
Are you involved in any upcoming ones?
Yes, I'm at the EuroSciPy.
So the Python Software Verband is also taking over the legal part of the EuroSciPy.
So we do the – somebody has to move the money and sign the contracts and stuff like this.
So I'm involved also and we use our software that we use for PyCon.de and EuroPython for EuroSciPy now, the web conferencing software.
We are involved in – I'm involved there.
But I'm also a little bit involved.
We have what's called the Python Unconference in September.
And we are – our software fund is a sponsor and we help and support a little bit.
So we are not the main organizer, but we help.
There will be likely – so we are very close actually – there will be PyCon.de in October in Munich.
And we are involved there and there will be next year PyCon.de and EuroSciPy next year also.
So – and I'm always involved to some degree in these conferences.
I'm not doing the main work for sure, but I'm on the mailing list and I'm somehow involved in organizing.
Yeah, that's cool.
And it sounds like there's a lot of conferences coming up in Germany around Python.
That's cool.
Yeah, there's several of them.
They have this bar camp, which is interesting in Cologne.
I myself, I'm just a participant.
Other people do this, which is pretty relaxing.
So it's a kind of a – also like an unconference.
So we have this unconference in Hamburg.
So there's several events we have.
So now actually we have not this one big one, but multiple smaller ones, which are more original, which can also be nice.
So people don't have to say, if I miss one, then that's it.
I have still two or three more alternatives.
Right.
A little bit of each is really great.
Final two questions, Mike, before I let you go.
When you write some Python code, what's your standard editor?
What do you open up to code?
Typically, I go with sublime nowadays.
Sometimes I use Wing IDE if I have some projects, which of course has a nice debugging and refactorization things.
For courses, I use Spider, which is kind of a scientifically inclined thing.
So I use it for my courses.
That's the one that comes with the Anaconda distribution, right?
Yes.
So Anaconda has it out of the box.
If you don't, if you just install Anaconda, you have it.
So Spider, it's not perfect.
There's sometimes crushes, but it's okay.
So of course, then I think it's, you don't have to tell people to install a different editor just to have one.
And they have a debugger and they have an object.
You can look at the objects, the Python objects for debugging and stuff like this, an interactive console, if you like.
But most of the time, of course, actually I spend a notebook anyway.
So, right.
Yeah.
The Jupyter notebooks is also really nice.
That's cool.
All right.
And the 80,000 plus PyPI packages, what's your one to recommend that people maybe don't know about?
The one that we talked about already is that Jupyter notebook is the killer app.
So if you don't know Jupyter notebook, you're missing something out in the Python community.
That's something you should go.
So that's very interesting to work with Jupyter notebooks.
Jupyter notebooks.
I always have a notebook open to just try something out.
If you have an idea, you can use it.
It's a very nice mixture between an editor, a full editor and the interactive prompt.
And that makes it.
Maybe that's not the real secret.
The one I'm looking right now is sconch.
You know sconch?
It's this interactive shell.
Yeah.
With an X.
Yeah.
There's an X, but it's pronounced sconch.
And I know Anthony Scopeparts pretty well.
We're hanging out at PyCon lately and he's a funny person and very knowledgeable on top of this.
And he wrote a very interesting tool which gives you a kind of a shell that incorporates Python.
So in a nutshell.
It's very interesting.
So you get a shell that incorporates Python.
And then I think it works on Windows.
So you get a much more powerful shell on Windows because the shell on Windows is typically not that great.
So if you need to work on Windows sometime, as I do for my courses, then this would be a good alternative to the workers.
Right.
Yeah.
That's cool.
Okay.
Great recommendation.
Yeah.
And you know, the story on Windows is getting better, right?
Like Steve Dower redid the installer.
So now the installer is not a complete challenge to like get Python on there.
The Windows 10 shell is a lot nicer.
They're bringing the Ubuntu binaries to Windows 10 starting in a month or two.
So it's getting better.
But yeah, it still is sometimes painful to work on Windows.
Yeah.
But in the compiling C extensions still not the smoothest experience.
No.
Let me just say VCVAR's bat was not found.
Right.
Yeah.
I have this message about a hundred times.
Gosh.
Yes.
All right.
Well, Mike, it's been really fun to have you on the show.
Thanks for sharing your optimization experience.
Thanks for having me.
Thank you very much.
Yeah.
Talk to you later.
This has been another episode of Talk Python to Me.
Today's guest was Mike Mueller.
And this episode has been sponsored by Rollbar and SnapCI.
Thank you both for supporting the show.
Rollbar takes the pain out of errors.
They give you the context and insight you need to quickly locate and fix errors that might
have gone unnoticed until your users complain, of course.
As Talk Python to Me listeners track a ridiculous number of errors for free at rollbar.com/talkpythontome.
SnapCI is modern continuous integration and delivery.
Build, test, and deploy your code directly from GitHub.
All in your browser with debugging, Docker, and parallels included.
Try them for free at snap.ci/talkpython.
Are you or a colleague trying to learn Python?
Have you tried books and videos that just left you bored by covering topics point by point?
Well, check out my online course Python Jumpstart by building 10 apps at talkpython.fm/course
to experience a more engaging way to learn Python.
And if you're looking for something a little more advanced, try my WritePythonic code course at talkpython.fm/pythonic.
You can find the links from this episode at talkpython.fm/episodes/show/66.
Be sure to subscribe to the show.
Open your favorite podcatcher and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, Google Play feed at /play, and direct
RSS feed at /rss on talkpython.fm.
Our theme music is Developers, Developers, Developers by Corey Smith, who goes by Smix.
You can hear the entire song at talkpython.fm/music.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Smix, let's get out of here.
*outro music*