Are you a web developer who uses Flask? It has become the most popular Python web framework.
And even if you've used it for years, I bet we cover at least one thing that will surprise you
and make your Flask code better. Join me as I speak with Miguel Grinberg about his top 10 list
for tips and tricks in the Flask world. They're great. This is Talk Python to Me, episode 264,
recorded May 1st, 2020.
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 talkpython. This episode is brought to you by Sentry and
Linode. Please check out what they're offering during their segments. It really helps support
the show. Miguel, welcome back to Talk Python to Me.
Thank you, Michael. Glad to be here once again.
It's great to catch up with you. It's been a while. We used to catch up a little bit more
when you were in Portland, but a little farther away now. So it's nice to see your face and
hear how you're doing.
I'm doing good. For those that don't know, I'm in Ireland, probably not forever. I think
eventually I will return to Portland. We will go back to have lunch every once in a while.
Perfect. Perfect. I'm looking forward to it, whatever that is.
Yes. But for the time being, yes, I am living in Ireland. The plan was to travel a little bit,
which of course with the current situation, not so much or actually not at all.
It's not the best time, but you have been there for a while. And I really enjoyed my time in Europe.
I'm super happy to be in Portland right now. Don't get me wrong. But I really enjoyed living in Germany
for a year because it was so cool to just go, hey, it's two hours on the TGV to get over to France and
to Paris. Or I could just drive down to Austria or whatever. It's a different kind of experience over
there, isn't it? It's really nice. And I'm really looking forward to civilization resuming
at some point and do that for a little bit more time before we return back to the States.
Cool. Well, I'm glad it's going well for you, even if you are a little bit restricted in your
day trips and whatnot, which I'm all behind, right? We need to do this to get through this. It's such an
insane time.
Yeah. I was going to say that I feel like I've been preparing for this situation for the last
few years by working remotely.
You know, that's really interesting. I totally hear what you're saying and I agree with you because
you and I talked before you moved to Ireland and I think you were thinking, all right, well,
where I'm moving to, I might not have a job there. So let me figure out how I can start laying the
foundation so that I could work anywhere in the world. And I just happened to be hanging out
outside of Dublin, just enjoying life and seeing things, but maybe still working for
somewhere in the States or somewhere else in Europe or even doing your own thing, right?
Yes. It's a little bit of everything actually. And the situation is luckily so far has not affected
my work life. It affected pretty much everything else in many ways, but I'm working for Twilio right now
and that luckily is going well and hasn't been affected at all because I was remote before. So
everything keeps going the same way for me. A lot of the company was not remote and it is remote now.
So there's been big changes for a big part of the company, but not specifically for me and my team,
which were, you know, we were remote before.
It's cool. You know, Twilio is a great company and I'm happy to hear you're working with them.
I wonder, do you think that for people like you and me and the thousands of others out there listening
who are already on the remote side of things, it's different for me because I don't have a,
like a in-office counterpart of my company, right? Everyone I work with that works with me on stuff
is all remote. So not so much for me, but I guess for folks like in your shoes where I used to be as
well, do you think this, I guess, forced remote work experiment that we're all on, do you think
it's made it a little bit easier for you in the sense that it's like leveled the playing field,
right? It used to be like, maybe there was a meeting with five people in the room and then there was like
you and one other remote person were kind of on the side. People would like pointed stuff you couldn't
see or whatever, but now everyone has to kind of be on an equal ground. Do you think it makes remote
workers a little bit better off in a sense? I think that will be the case for teams that are
partially remote, partially in office. That is not my case. Yeah. Even though company,
like your team individually, it's a hundred percent remote. It's 100% remote. Basically what I do at
Twilio is I work on editing articles for the blog, the developer blog. My team is, you know, editors.
I work on the Python side and we have people for different languages and that's my team.
Right. You probably have to coordinate about like, Hey, we're going to have an article on this API
solving this problem. Exactly. I'll do one in JavaScript. You'll do one in Python and let's
figure out what the app is, right? We have one meeting a week to basically coordinate. And then
the rest of the time we work with external contributors, right? Also remotely. So, you know,
for our team specifically, nothing has changed, but I would imagine, or actually I should say that the
one thing that changed is that we were getting asked for advice or all this new people who are forced
to work remotely want to have, you know, tips and basically pick our brains.
Tell us how you do it, right? Tell us how you make this work.
How could you make this work, right? I think it's so interesting to watch the news where they have,
you know, like multiple people on the show or things like the daily show or stuff. I'm especially
thinking of the news shows with the news anchors where they all have had to start working from home.
And you can see like week after week, they slowly are figuring it out, right? Yes.
They had like super echoey laptop audio for their microphones and they're slowly starting to sound
like ironically, like you and I do. And I think that we sound better. I mean, obviously we do
recording and stuff, but also because we've had to live a hundred percent as with this as our professional
interaction. And so to me, like sounding good and looking good, like we both have HD cameras,
we both have good microphones that is kind of like getting dressed and looking good for business,
right? Like when you show up for a meeting and you sound horrible and echoey, people don't want to
talk to you, right? That's not a good look. There's a bunch of layers that we're all cultivating here.
So what I'm very excited to know is what's going to happen at the end of this. I think a lot more
people are realizing that it works. You can work from home and you get all that time, you know,
the commute time back. So I suspect a percentage of, you know, all the people who are now forced to work
remotely will like it and we'll decide that. Yeah. And I can really do this.
I think we're not going all the way back to the way it was. It's going to be some of these
advantages that people were unwilling to try are going to be seen as advantages are going to stick
for sure. Yeah. Yeah. How about we talk about some flask, huh? Something that you've been definitely
passionate about for, for many, many years. So we were talking before and you were on episode 48
over four years ago, we talked about building apps with flask and then you were on episode 121,
where we were talking about microservices and really with like a bit of a flask angle there as well.
So you've been a fan of flask for a long time. Yeah. I was a user of flask first and probably told the
story in the first episode, but you know, quickly I wrote my blog with flask and then not knowing what
to blog about. I decided to blog about flask at a time where, you know, I wouldn't say that it was an
obscure framework, but you know, certainly didn't have the following that has now. So my articles for some
reason were the first that, you know, outside of the frameworks on documentation and it started growing
at the same time. I decided to blog about it. Yeah. You just catch the wave at just the right time.
Exactly. But at the same time, you know, you saw the framework, you're like, no, I'm not going to do
it in Django or whatever else. I'm going to do it in flask. Right. So there's some, you know, picking
the right ideas. Yes. And part of my, I'd like to think that this was a little bit of my doing. I
showed why, you know, in many cases flask was the better choice by writing tutorials, usually in my blog
and showing actual examples where you could do things that, you know, usually are considered hard
and they're not so hard when you look at them through flask. Yeah. To me, flask, I'll compare it
to Django because that's its biggest alternative, right? There's certainly all these other new things.
There's so many new web frameworks coming. I don't know. I'd like to hear your thoughts on this actually
is there's, there's so many new cool little frameworks. You know, we got FastAPI, we have
API star, we have Sanic and just all these, they're not all necessarily leveraging the new asyncio stuff,
but a lot of them seem to be like, Hey, these other frameworks didn't really solve my problem
because they didn't support async. So we're going to create something that maybe leverages type hints
plus async. That's kind of like flask. But what do you think about some of those? Like,
where do you see the action there? First of all, I'm very excited that the model for all these
frameworks is flask, right? They all do kind of like flask, as you said. Yeah, that is what was
really surprising to me. So if you compare flask against Django or against pyramid or against the other
frameworks and you look at their popularity, like I think flask is, we were talking neck and neck,
but I think actually, if you look at the newer projects that haven't been around for a while,
flask is pretty clearly ahead of Django in terms of popularity. It's like there's a ton of Django
apps that people are still working on. So when you ask, do you work on Django or flask? It's a lot of
times I think it means I work on a Django app that's been around a while. Not that there's anything wrong
with Django, but just in terms of that growth. But then if you look at flask as the, like the idea of it,
that all these other frameworks seem to think that this flask style,
yes, slight adaptation is what they want, right? Yes. A big reason for that, I think is the,
we are moving a lot of the, the logic, the business logic and applications to the client side,
right? With all these new JavaScript based frameworks for the browser, right? So for sure,
what's left to do in the server is really the database storage related actions and maybe
authentication, surely authentication, and that's it. So if you look at a framework like Django,
you can do that really well, but it has a lot more components that you really have no use for.
And, you know, all these new frameworks modeled after it sort of give you just the API portion of
your server side part of your project. Right. It's kind of just enough server side.
Yes. Right. Yeah. I would say that it has a little less and then you can pick,
you know, the right extensions to, to make it exactly what you want.
Yeah. Right. Right. Add on. Yeah. That's a good point. I'm still a fan of having a decent amount done
on the server side. I, I don't know. I just, I like the instant, you know, I don't know. It drives me
crazy to see these pages sort of like build up as I interact with them. You know, you'll see like,
oh, you're logged out. No way. Half a second later, I'm logged in and like, you know, just that kind of
stuff. I'm not a huge fan of. You should find the right mix between, you know, server and client.
I think people are too quick to go to build everything as a single page app, react to view,
angular, you know, those types. And they, they don't think about doing it a right balance. Sometimes
you don't expect everything to be done in a single page. It feels weird. The whole page is changing,
but it's really done in react, for example, which is slow and weird. It messes with the back button
in the browser. I prefer to basically use the single page app only when you see a clear benefit.
You really need like an interactive thing. I'm building like a little dashboard I'm exploring
or something like Gmail or something like it's perfect. Right. But it shouldn't be the one hammer
you hit everything with in the web.
My blog, the blog that I wrote six, seven years ago, when I started with Flask, it's still a
traditional application server centric. And, you know, it's just fine. It has a little bit of
JavaScript sprinkle here and there to make it a little bit nicer, but you know, it's mostly server side.
And I think for a blog that works really well.
Yeah, I agree. So you're talking about the front end frameworks. Like I agree, like don't overuse
them whatnot, but sometimes they make a lot of sense. What ones do you like right now?
My preference, and this is going to generate, generate a little bit of disappointment in your
audience. I think it's a vanilla JavaScript. That is the framework or the no framework that fits my
brain the best. So I can do whatever you want in vanilla JavaScript. A few years ago, I would say
jQuery. These days you don't really need that. The jQuery was a layer that will make all the browsers
sort of uniform. And these days the browser, the browsers are pretty good at being uniform with each
other. So that's my favorite. Out of the real frameworks, React is the one that I've used the most,
but only for simple apps. What I've seen is that all these dependencies that are generated
between all the parts of the page, it's very easy to get them completely out of control as the project
grows. At least I personally find having a handle, like for example, when writing vanilla JavaScript,
having a handle of what part of the page it's related to what other part makes it for a much faster and
dynamic application. For small examples, I think React is a good model. And that is what I use.
Nice. If I had to throw my vote in for one, I'd put it on Vue. I like VJS a lot. Yeah. I like it just
quickly, just bring it in, just include a JavaScript file, you know, pull out an ID and say,
this little sub part of the page is now an app. I really like that.
Yeah. Vue will be my second choice actually. Yeah.
This portion of Talk Python to Me is brought to you by Sentry. How would you like to remove a little
stress from your life? Do you worry that users may be having difficulties or are encountering errors
with your app right now? Would you even know it until they send that support email? How much better
would it be to have the error details immediately sent to you, including the call stack and values of
local variables as well as the active user stored in the report? With Sentry, this is not only possible,
it's simple and free. In fact, we use Sentry on all the Talk Python web properties. We've actually
fixed a bug triggered by our user and had the upgrade ready to roll out as we got the support email.
That was a great email to write back. We saw your error and have already rolled out the fix.
Imagine their surprise. Surprise and delight your users today. Create your free account at
talkpython.fm/sentry and track up to 5,000 errors a month across multiple projects for free.
Flask is on the rise. I think it's on the rise in its own right. And I think it's
on the rise in the sense of its API as we talked about. So let's dive into the 10 tips that we're
going to talk about. Yes. 10 tips. Yeah. What do you got for number one here? Okay. Number one,
it's actually very specific to APIs. Okay. You do not need to use the JSONify function anymore. So this is
in recent Flask releases. For many years, if you needed to return a JSON response, you had to
call the JSONify function, which would take a dictionary or list and convert it into the actual
payload that goes out to clients. Right. So if I've got a view method and I wanted to return JSON,
I can't just say return a dictionary or return a list and have it internally serialized to JSON.
Right. That'll like not work. Not until now. So I've always done JSONify as well. Now what can I do
instead? So basically now you return a dictionary and Flask will itself say, okay, this, this goes out as
JSON. So it will JSONify the response, set the correct content type and all of that.
So when I think about this, what else has to be done to make this work? Do I need to add anything
like to the route decorator to say the response is JSON? No. Or is it enough if the client connecting
says, except type is application slash JSON, or what do I need to do? You don't need to do anything.
So this is always Flask looked at the type of your response that you're returning your view function.
There were always different behaviors depending on the type. So if it was a string, it would send it as
text. If it was a response object, it will send it as basically whatever you said in that response object
and so on. And now there's one more type. If you return a dictionary, then Flask says, okay,
this is JSON. It basically sets everything up for the response to be all done for you. So it's really
great. I'm not importing JSONify anymore. There's no need at all to import that function and then have
it in every single last line of all your view functions.
Yeah, that's really clean. I definitely like that. That's something I've really liked about the
Pyramid Web Framework is you've been able to do that the whole time. You just return some data type
and it'll serialize it. Yeah. So really glad to see this is nice and clean. And yeah, I think when I
first started doing Flask, I was like, oh, I'm going to try to return a dictionary. Oh, it doesn't like
that. Now I have to go hunt down. So ran across JSONify and I didn't realize that that had been
sort of more made more general. So you don't have to. That's great.
Yeah, it's really nice. For many years, I used the decorator specifically for that. It was
an at JSON that I even taught in many classes how to create a decorator that will take that response,
a dictionary. Absolutely. And I've created a decorator exactly like that that takes in the
decorator, you specify the Jinja template and you return a dictionary and then it'll like send that,
it'll render template with that dictionary as well. I'd love to see those kinds of things built more
into Flask. I mean, I know this one's no longer relevant, but there's a couple of things like that
that would be kind of cool, I think. Yeah, very nice. Okay. So no more JSONify
API is a little bit less coderad. It just makes it cleaner. I love it. All right. Number two.
Number two is do not store sensitive information in your user session. I see this a lot. It's so
convenient. You have, you know, from Flask import session and then a session works like a dictionary
and it's so tempting to write any kind of information there that, you know, in the next request from the
same client, you can recover. It's preserved per client, right? So...
Right. Like if you log in, you could put like the user ID in there. And so then the next request comes in,
you could pull them back.
So you certainly put the user ID. So it's very important to remember that unless you configure
Flask in a non-default way, those sessions are not encrypted and they are sent in cookies to clients.
So the client is storing all that information that you put in the session dictionary. So you should
definitely never store information that you do not want to be public.
at least the user could go in there and see it or they could go in and they could mess with it,
right? They could tamper with the cookies and whatnot, right? You definitely don't want that.
So that's actually a good point. They could not, clients cannot modify it. The cookie is a secure
cookie. It has the content. It's not clear text, but it's also not encrypted. It's in base 64 encoding,
which is very simple to...
It's like visually encrypted, but that's all.
It's visually encrypted, right? So it's base 64 encoded, but there's also a crypto signature
in the cookie.
I see. Okay. So it's tamper proof.
Correct. If you make any changes in the client and then try to send that cookie again to the server,
Flask will say, no, this is not, the signature is incorrect and it'll throw it away. So that's not
a problem. So it's safe against tampering, but it's really not safe against seeing what the
information is. So never store cookies or, I'm sorry, secrets, passwords, you know,
nothing of that sort.
Yeah. So I've never used the session feature of Flask. I've always just said, I want to store a
cookie. And it just has like one piece of identifying information to like carry on that session. And then
I'll go back to the database to get the rest, everything else, right?
Okay.
Should I not be using this? Like, should I be using session? Should I look more into it?
Session is actually very convenient and Flask has a plugin architecture. You can install different
types of sessions. The default is the cookie or secure cookie based session that I just described,
but there's an extension called Flask session, which provides sessions that are stored server side.
So this extension provides a number of storage mechanisms. You can store them in files,
pretty much in the style of PHP. If you've seen how those are stored, you can store them in a database,
right?
Through SQL Alchemist, for example.
Probably Redis. Yeah.
There's a Redis backend as well. So Flask session will be, you will have to do that if,
if you want to store sensitive information in your session and then you will be safe,
right? Because the only thing that will go on the session cookie in that setup will be the session
ID, but all the information will be safely stored in the server.
Okay. Yeah. That sounds like a pretty good thing. And the server side bit is nice, right? So you can
store those things, but not actually send them. And even if it's not because it's sensitive,
maybe it's not reasonably serializable or it's not, maybe it's just a lot of data, right? You don't
want to send like cookies are limited in how big they can be. And you don't want to exchange like
huge cookies anyway.
They need to be there. They are encoded to JSON before the base 64 encoding is applied. So the,
whatever you store in the session needs to be JSON compatible. So a string, a number,
a list of, or a dictionary. So yes, definitely there are some limitations.
Cool. All right. What's number three?
Kind of related.
Oh, before we move off this one though, I want to do say one thing really quick,
maybe a 2.5, 2.7, something like that. You're talking about exchanging these cookies. And I was
kind of thinking, well, okay. So the user really needs to be careful about like, it'll be on their
file system somewhere as a stored cookie. They can go to their dev tools and look at their cookies and
whatnot, but it's kind of safe to the world. That's making a really big assumption that that
connection is encrypted.
Right. Yes. And actually these 10, maybe we should have an 11th tip, which is always use HTTPS.
Yeah. Yeah. That was going to be my 2.5 is like, let's encrypt, right?
Yeah. You always have to have encrypted servers when you deploy for production. Even if you think that
you have nothing that's sensitive in this day and age, there's really no reason to risk it because
you can get a free SSL certificate from Let's Encrypt.
It's incredibly easy to set it up for Let's Encrypt.
It's very easy to set it up.
Yeah. I had resisted it because I was like, I don't really want to learn how, I already have this other
SSL certificate I bought. It's like good for three years, but I don't want, and then I finally just
said, all right, I'm going to find out, like, I'll just get Let's Encrypt working just so I don't think
about renewing this other one. And it was like 10 minutes later. I'm like, oh, that was really easy.
Yes.
That was learning. You know, the second time it's even quicker.
Yes. And the certificates last, you know, they're short-lived. They last for three months,
but you set it up so that they automatically renew. And it's something that you never need to think
about. They basically, they just work. So yes, absolutely. You always have to have SSL encryption
on your sites deployed to production.
Yeah. Two more aspects to that. Obviously this, we think of privacy when they think encryption,
but SEO, Google is taking into account whether a page is secure or not as well these days. And
they're also taking into account performance. One of the really nice ways to get performance these
days is to just do HTTP2, right? And I'm pretty sure that only runs over SSL.
I'm not so sure about that. Maybe.
You know? Okay. I can't remember. I feel like I tried to set it up before. I don't know. I think
I'll mess around while we're talking and figure it out.
We should definitely figure it out. And in general, I've found that you can add all the HTTP2
solutions, you know, outside of your web application. I don't find that I need to worry
too much about that within Flask, for example. You put a reverse proxy in front that will take care of
that. That's actually the same idea that I'll apply to the encryption. In general, I prefer to
leave that to tools that, you know, that do that well, do it in native language, not in Python.
It's way faster and more efficient. So all those things are good to have, but luckily they haven't
changed, at least for me, how I write my web applications in Python and Flask.
Yeah. Same. Yeah. I'm doing HTTP2 for my stuff. And it's like, most of that is around serving the
CSS and the images and the JavaScript through Nginx. And like, that's even before you talk Python,
right? Okay. So let me read something really quick and you interpret it for me. This is from
SSL.com. It says, browsers distinguish between clear text HTTP2 and HTTP2 over encrypted TLS as two
different protocols. As of this writing, none of the major browsers support H2C, which is a clear text
version, which means TLS encryption is mandatory. So the protocol specifies a non-encrypted version,
but apparently the browsers... None of the browsers do it. Right. At least as of 2000, November,
2018. Right. So maybe they have, but I'm surprised if they'd be... I don't see why they would. Right.
Exactly. So I think theoretically you don't need SSL, but in practice you need SSL. So one more reason,
I guess there. Cool. All right. More secrets. Number three. Okay. Another secret related one.
You should use a .env or .env file to store your secrets. I'm sure if I go search GitHub for the
standard names that people assign to AWS secrets or even Twilio passwords, you know, all those things.
All these things.
I'm sure I can collect a bunch of them, right? That people put in source code and then they forget.
Yeah. And that's fine until it's not. It's fine because you're like, oh, we're never going to open
source this. And then somebody does and they don't realize it. And then bad stuff happens.
S3 buckets are exposed and so on. Right. So you should get used to never write a password or a
secret on an API key directly in the code, even if you're doing it for a quick test, because it happened
to me many times. I think that I'm going to do a quick test, but then that evolves. And eventually
I said, oh, this is a good thing to show in a gist. And then off it goes to GitHub. So never do it.
And then you'll be safe. What you need to do instead is to replace in the place where you are
going to write the password or secret, just read an environment variable and then get used to always
have the secrets that you use in your applications in environment variables.
Right. That's helpful for things like Docker as well. It helped you create these more isolated
reproducible elements. So that totally makes sense. And I've heard put them in environment variables,
but what's the story with the .env file? How's that relate?
The problem is that people find it annoying to have to set environment variables because when you set an
environment variable, the life of that environment variable is the session, right? If you close your
terminal window, let's say we're talking about development, right? So at the end of the day,
you turn off your machine. The next day, all those environment variables are gone, right? So my
recommendation and something that works really well with Flask is that you put all your environment
variables in the .env file and then Flask in recent releases, if the package python.env is installed,
we'll just import all those variables when you run the application.
And it basically sets them as if into the environment. Like if you ask for them from the
environment dictionary, they'll be there.
They'll be there in the same way as if you had set them by hand on your terminal before running
Flask run.
Okay. What's the name of this package?
Python-.env. D-O-T-E-M-V.
Yeah. Yeah.
There you go.
Cool. I'll put it in the show notes.
So even if you don't use Flask, this package makes it so simple to import a .env file. You just
need to call a function load.env. That's it.
And then after you call that, all the variables that you stored in the .env file will be in your
environment.
So I totally agree with this, but I always wonder what people use to persist and version and keep
those types of things.
Where do you store the stuff?
So if you got a new computer or you got a new team member, how do you get them this information?
I'm going to tell you what I do. Some people may like it. Some I'm guessing won't. But what I do is I
create a .env template. I usually call it .env-template or something very clearly that you can see that it is an
example of how your .env file should be structured. And in that template file, I write the variables,
the equal sign, and then I leave it empty. So when you're installing your application in a new machine,
you copy the .env-template to .env, and then you fill out your secrets. And yes, it is annoying,
but it's only the first time when you're installing a new application. That's the only time you have to do
it. And then it works. Second to that, you have to put the .env file in your gitignore file,
because you, of course, don't want to commit that on purpose or by mistake to source control.
Right. That kind of defeats the purpose, right?
Of course.
I think that might be a default in GitHub if you pick the Python ignore template. I can't remember,
but I think so.
No, actually, I wouldn't say that. That was my complaint. I don't believe it is.
Oh, it's just .env, not .env?
Right. I don't think they have .env, even though it's actually fairly standard. Many technologies and
many languages and frameworks use it, but I don't believe it is. I'd like to see it there by default.
Yeah. Well, you know that these gitignore templates are like projects on GitHub, right? So like
github.com/github slash gitignore is the project where those are kept. We could do a PR,
see what they think.
We should do a PR, definitely.
We should do a PR, yeah.
This portion of Talk Python to Me is brought to you by Linode. Whether you're working on a personal
project or managing your enterprise's infrastructure, Linode has the pricing, support, and scale that
you need to take your project to the next level. With 11 data centers worldwide, including their
newest data center in Sydney, Australia, enterprise-grade hardware, S3-compatible storage, and the
next-generation network, Linode delivers the performance that you expect at a price that
you don't. Get started on Linode today with a $20 credit, and you get access to native SSD
storage, a 40 gigabit network, industry-leading processors, their revamped cloud manager at
cloud.linode.com, root access to your server, along with their newest API and a Python CLI.
Just visit talkpython.fm/Linode when creating a new Linode account, and you'll automatically
get $20 credit for your next project. Oh, and one last thing, they're hiring. Go to
linode.com slash careers to find out more. Let them know that we sent you.
Good advice. Another thing that I've seen, this is not the same, it's the same vein, but it's not the
same thing, is, and this honestly sounds better, but also pretty good, is usually we're using virtual
environments for web apps and any meaningful app, right? So the virtual environment you create has an
activate script, you can set environment variables there. So anytime you activate the virtual environment,
it's always got its environment variables set. It's kind of the same, you create a new one,
you got to reset them, but similar.
Yes, it's a little bit more difficult to remember to do it when you do a new installation.
Yeah.
But yes, definitely a good readme pointing you to do it should help and you achieve the same result.
I think the one difference is like the .env template explicitly kind of reminds you that
there's some kind of thing I've got to do, whereas the virtual environment is like magic. Like it's good
when it's set and it's working, but there's no indicator that this is a step you need to do.
Yes, that is a good point because when you call the load.env function from this Python.env package,
if there's no .env file in the file system, it'll print a warning. So you will see a warning in the
console.
Nice. That's good. Perfect. All right. What's number four?
So this is not specific to Flask, but for many years, people who use Windows, they're sort of
treated like second class citizens, right? Because most tutorials I've written for Bash and, you know,
Unix based.
Dot space VMV bin activate. Like, wait a minute, that doesn't work.
The dot doesn't work. The bin doesn't work. What is all this?
Right. And then the forward slashes versus the backward slashes that you use on Windows.
So in recent years, there's also Chromebooks, which are another group of people, the users of Chromebooks,
who sort of felt at a disadvantage because you have a perfectly fine machine where you should be able to
write, develop code, write Python. But for many years, it was not possible or it required hacks on the
device itself. So these days, both Windows and Chromebooks both have Linux emulation solutions.
They're not the same, but the end result is that you get a Linux prompt where you get Bash or C shell
or your favorite shell that you'd like. And then basically you can run Ubuntu Linux in your Windows or
Chromebook machine.
Yeah. Nice.
So I don't use Windows so much now, but I have a Chromebook. I can do pretty much anything I do on my
Mac laptop on the officially supported Linux emulation on the Chromebook.
So definitely take a look at the WSL, the Windows subsystem for Linux, if you're on Windows or the
Linux files support, if you're on Chrome OS, because on both, you can run the Ubuntu or other
distributions. That's the default, but you can use a different one if you like. And you can run Python,
you know, recent versions of Python, Flask, and all of that works exactly like it would on a
Unix or POSIX type OS. So you will be able to follow tutorials using the standard instructions
that you see for Unix.
Yeah, that's cool. And the Windows subsystem for Linux 2 was just released not long ago,
which is a big improvement, I understand.
It's actually an improvement in performance and it's actually more directly, it's less of a VM
or virtual machine solution.
Right. It's kind of more linked between the different two environments and apps and whatnot. Yeah.
Like you can open Explorer from your Linux and to get your file system, stuff like that. But I think
actually the Chromebook story is bigger because one of the important places people might want to use
both Chromebooks or rephrase that they have a Chromebook as their only option and they want to learn Python
or programming is in the educational space.
Oh, yes.
So many kids have Chromebooks. My daughter has a Chromebook from her school and if they wanted to do Python,
they could maybe do some online thing, maybe? Or the answer was no, you don't do Python, right?
It's actually hard to even an SSH connection to a remote server. You can, but it's tricky. It's not
immediately obvious how to do it. But now you can run your own local Ubuntu distribution in the Chromebook.
Nice. Cool. That's a big deal.
And it's all official. It doesn't require any hacks. It's all sanctioned by Google and developed by Google as well.
Cool. And shout out to the folks over at Canonical for releasing Ubuntu 20.04 LCS.
Yes.
The first LCS release.
Yeah. In two years. So it was super awesome. And it comes with Python 3.8 as the default and Python 2 is not even installed.
So the Python story is better there. And obviously just the new Ubuntu is nice. Cool. All right. Number five.
Number five. So this is the thorny one. A lot of people to this day don't understand the contexts in Flask.
Most people don't see this, but they only learn about it when they get an error. And there's actually two different errors.
And they're so similar that people think there's only one. And the two errors are you're working outside of the application context. That's number one. And then the second one is you're working outside of the request context.
And I suspect this is where people are going just statically saying Flask.request.property. But that's not set.
Right.
Because they're outside the context. Yeah.
This comes all from the philosophy of Flask, which is to make all these variables, let's call them variables, that are global in nature to be magically available.
So you import, for example, current app or your import request, and then you just use it as if it was a global variable. It's actually, there's a little bit of magic underneath these imports, but you use them as global variables.
And if you use them in the wrong place, then you get the error.
Right. So once the context is created, these are what, thread local storage, basically?
Yes. The implementation is based on thread local storage. So they basically belong to a thread.
Right. And that's the request coming in through like micro WSGI or something like that. Sets that and then the rest of your app just has it.
Correct. So the interesting thing is that people don't realize that these are very different.
If you get the, you're working outside of the application context error, that means that some piece of code wants to know what the application is.
And all you need to do is set the application context yourself.
If you look in the Flask official documentation, it shows how to do it. It's a single line.
There's even a context manager to do this.
So you set the context and then your code will work and you solve the problem. That's it.
Yeah.
The issue is when you get the other one and people confuse the two.
But if you get, you're working outside of the request context, that typically means that you have a bug in your application.
You're trying to get information about a request and there's no request, which means that you're running this code.
Right. Maybe you kicked off a thread or something weird thing like that.
Yeah.
You're doing it in a place where there's no information about the client.
So you know nothing about a client or a request.
I see.
That indicates that you have a bug and people find crazy ways to fix that basically to avoid the error.
And one that I see a lot is that Flask has this way to create a test request for unit tests.
Right.
If you create a test request, then you can invoke request dot something and it will work.
But the information that you get is all fake.
So, I mean, the fact remains, you're probably doing something in a place where you shouldn't be doing it.
So, application context, if you get the error, you set the context and you're good to go, it's perfectly fine.
Request context, you need to look at your code, you probably have a bug.
You're doing it wrong.
Cool.
All right.
What's number six?
Number six is still related to this topic.
I've seen many, many applications that have, for example, they have Celery workers or any other type of auxiliary processes, maybe cron jobs, you know, all those things.
So, let's say you have a web application written to Flask and you're using Flask SQLAlchemy for your database.
So, when you go write the Celery side or the cron job, what do you do?
You create all the models using Flask SQLAlchemy.
And that extension has a very nice way of managing your connection.
You don't have to worry about it, actually.
Right.
Create the engine, create the connection, create the table, all that.
Yeah, right.
All of that is done.
You don't do any of that, right?
When people start coding their Celery workers or cron jobs, they say, well, okay, I'm going to have to do all of this myself.
They create their SQLAlchemy engine and they have to figure out crazy ways to get the models which are written to inherit from db.model, which is a Flask SQLAlchemy class, you know, to inherit from the base, you know, the declarative base from SQLAlchemy.
And they invent a lot of crazy ways to make that work.
And the fact is that you don't have to.
You can create a Flask instance and instantiate Flask SQLAlchemy and then not start a server.
And you can use the database just fine.
Right.
If you just don't call Flask.run, you're kind of everything set up anyway, huh?
Don't run the server, but create a Flask instance in the Celery worker, in the cron job, it doesn't matter.
Just create, call the create app function to make it an application, configure it exactly like you configure it for the server, but then don't start the server.
Yeah.
And then that gives you access to using all the extensions.
You can use the database through Flask SQLAlchemy just fine.
There's absolutely no problem.
Another big one is sending emails.
So if you use the Flask mail extension, it's exactly the same thing.
You can send an email from a Celery worker.
You don't have to look for a different library.
You can just create a Flask application instance, configure it, and then Flask mail will work just fine.
Yeah.
And well, sending email is exactly why you would do this on another thread or in a background.
Because if you're sending one email, fine.
It's probably okay.
It's not ideal, but it's fine.
But I ran into this thing where I had thousands of people sign up to get notified when I posted a new office hour.
Because I have free office hours for people to take my courses.
They can drop in on Zoom and chat and whatnot.
When that started to grow, I remember hitting it.
And it literally timed out the request, trying to send the emails.
And then it was halfway through sending the emails or some percent through.
But I didn't know how far.
So I didn't know how to go back and send the rest of the emails.
I'm like, well, the other rest of the people are just not getting sent because I'm going to email the first half again.
Right?
It's just like, it's not a thing you do as part of a request.
It's really sad that similar stories happened to me.
And yes, that's actually a good reason to send the emails to a background job.
And then it can take as long as it needs.
But yes, you would need to create the Flask application instance.
You will need to set the application context.
Because in a particular case of both Flask SQLAlchemy and Flask Mail, they need an application context because they need to get the configuration.
That's all they need.
That's actually, they don't really care about Flask itself.
But they have the configuration variables in app.config.
So you need to set the application context.
So they need the first part.
They need the app part.
Yeah.
Right.
They just need to know where the app is.
So only so that they can get to the configuration.
And then they can know what the database is or what the email server is.
So definitely do it that way.
And then you can have a consistent way of working with database or emails between the server and your auxiliary processes.
Yeah.
That's great, great advice.
Now when I'm doing something like email, even if I'm just sending one, it's on a background job.
It's not part of the request.
It should always be.
And people don't realize this, but sending an email is actually very slow.
It takes a few seconds if you're lucky.
Right.
Well, and it also depends on things you don't control, right?
Like you probably control your database somewhat.
But this is like some external mail server that's then talking to some other thing.
Yeah.
Yes.
And, you know, many servers introduce artificial delays for security purposes.
There's a lot of tricks that many servers implement.
The end story is that sending an email takes two, three seconds at least.
Yeah.
Just one.
At least.
Yeah.
So it should never be done in the server, you know, in the foreground of a server route.
Right.
Absolutely.
All right.
Number seven.
This one I kind of nudged you to cover.
Yeah.
This is a good.
Because I'm a fan of it.
But yeah, tell us about this one.
I'll jump in as well a bit if you want.
You surely know this one better than me because I found out a few days ago when you pointed this out.
But secure.py is a project that provides a lot of security settings around how you configure your cookies, your HTTP headers, in your requests, actually in your responses.
Not only for Flask, but for a lot of frameworks.
A really long list of frameworks.
Yeah.
This is one of the things I really like about this project.
It's because if I go learn how to do secure headers in Pyramid, then I go write my Flask API.
I've got to like rethink, okay, well, what does this default to?
And then how do I do it?
And what's cool about this is it's like literally one line, one piece of middleware or callback.
And you've got all these things added.
And it works for Flask, Pyramid, Django.
Like Starlette and...
The newer frameworks, right?
The AsyncIO frameworks.
Right.
All the core, which we'll talk about, Responder.
Like it has support for all.
So you just do the one thing for that framework, the one line, and then you're good.
All right.
So tell us about like why do we care about these things?
What is this?
There is a number of things that the default configuration for Flask and for all the other frameworks, they don't do.
And the reason why many of these things are not set by default is that they don't make sense during development.
I mean, that's one of the reasons.
Yeah.
Like strict transport security, for example.
Right.
Like you don't want to run SSL to just run localhost, right?
Exactly.
That would be an unnecessary complication.
Or setting the secure bit on your session cookie.
That's another thing that you will not do when you're working on your application, but that you definitely need to do when you deploy the application for production.
Right.
If I have that right, that means I'm only allowing the server and the browser to exchange that cookie if it's an SSL request.
So maybe I type the domain name, but I don't put HTTPS at the beginning and it does a HTTP and then an HTTP redirect to the S.
It's a very clever hack that some people exploit.
The browser will send your cookies unless told otherwise, regardless of you going to the site via HTTP or HTTPS.
The browser doesn't care.
Unless you tell the browser that the cookie should only be sent on the secure connection.
So the default is not set.
So cookies in Flask are not secure.
What people do is they call your site with HTTP and that basically forces the cookie to go from the client to the server on an encrypted connection.
Right.
And it can be intercepted.
Right.
And then probably your server will say, well, I don't have HTTP.
It'll do a redirect to the same URL.
But it's too late.
It's too late.
The cookie's been exchanged.
Yeah.
Time that's too late.
Exactly.
The cookie has been, you know, traveling the network, you know, unencrypted.
Yeah.
Definitely.
This is a good way if you don't want to think about security.
And, you know, ideally most people, they're not security experts.
So this is a good way to make sure that you have the baseline of your security protections all in place.
Yeah.
So some other things that it does is it prevents your site from being embedded in an iframe in another site automatically.
Right.
So people can't spoof yours, like wrap it with something else.
Yeah.
It turns on strict transport security, things like that.
Yeah.
The list of things that they do is actually way more than what I would have done myself or what I do myself by hand.
It's definitely worth checking.
It comes from the OWASP, like, which is a web security group.
It comes from their recommendations and it just automatically adds it.
And I imagine if there's a new recommendation, it'll just pick it up when you pip install upgrade this and you'll get the newer ones, which I think is nice, like kind of like versions your security.
So, yeah, it's really easy to use and I dig it.
So even if you're a do-it-yourselfer, it's a good place to learn all these things.
As I mentioned, there are many in that list of things that they do that, you know, they were not on my radar.
At all.
Yeah.
Like the iframe one was not on my radar.
Yeah.
Me neither.
Right.
Yeah.
So very good project.
Yeah.
Cool.
All right.
Number eight.
So HTTPY is a very nice project.
So we're used to see when we look at tutorials, people use curl to show how to send a request on the command line.
And curl has a somewhat unfriendly structure, especially when you need to send API requests that have JSON.
JSON payload.
So what I've been using for the last few years is this Python project called HTTPY, HTTPIE.
And that is a much friendlier command line HTTP client for mostly for API use.
Yeah.
I love this package so much.
It's one of the first things I install in a new server.
It is so much better than curl.
I almost never install packages in the global Python.
I always create virtual environments.
But HTTPY is in my global Python because I always use it even if I'm not working in a Python project.
So I always want to have a copy of it readily available on my command line.
So, for example, if you need to send headers, there's a syntax where you just use header name, colon, and then the value after you put the URL.
If you want to send JSON variables instead of the colon, you use an equal sign.
And there's a number of shortcuts that you can use to create an HTTP request very easily.
And not only get requests.
You post and put and all the harder ones as well.
Yeah. So once you install this, probably in your semi-global namespace with a --user type of thing, then you have two commands on your terminal.
You have HTTP and HTTPS.
And then you just give it a URL or whatever.
It's really nice.
Right. It's actually the method and then the URL.
So you can say post and then the URL.
And then you add your headers and your variables and off you go.
Yeah. And one of the things I really love about this is the response is color coded like a code editor.
All right. So you get like syntax highlighting on your responses and on your headers, cookie values and everything.
It's great.
It's very nice. And I rarely use code anymore now.
Yeah. Same. Love it.
All right. Number nine.
I talked about these new frameworks coming along because Flask and Django and Pyramid and so on don't inherently support AsyncIO.
And a lot of them are growing to do that.
But a lot of people want to use AsyncIO with Flask.
I think you had Philip Jones on your podcast at some point to talk about this.
Yeah, absolutely.
He went and created from scratch a clone of all the Flask classes and methods within those classes.
So basically he created a full clone of all the Flask APIs.
And that project is called Quart.
Nice.
The difference with Flask is that it runs on AsyncIO.
So you can create Async view functions.
I believe at this point he has even added some support for some Flask extensions.
It's almost entirely compatible with the extension system as well, he said.
So I don't think it's 100%, but most of the common extensions will still work with Quart, which is pretty cool.
The common extensions that don't do any blocking work, then yeah, they will work on Quart.
So it's definitely something interesting.
He's actually involved in this effort that's starting to add AsyncIO support to Flask as well.
There's a pull request, a first pull request.
I don't recall if it was merged already, but it's close to be merged to add the first shy implementation of AsyncIO support within Flask.
He's involved with that effort.
Otherwise, if you want to have full support for AsyncIO today using a very familiar Flask and all the Flask features,
then Quart is actually a very good choice.
Yeah, it's a super good one.
All you have to do is replace the word Flask with Quart.
If it's lowercase Flask, it's lowercase Quart.
If it's uppercase Flask, it's uppercase Quart.
And then you have the API.
You do have to get the zen of AsyncIO and Async and await and all that, which is a different way of thinking,
but it's super awesome once you get it.
Yeah, very, very nice stuff.
I guess that'll just kick you down the path to go,
okay, well, now I need to figure out how to do Async SQLAlchemy or Async Redis or Async FileIO.
Right.
I mean, it's like a, it's a layers of exploration to take full advantage of it, but it's very,
it's a very cool framework.
And I'd love to see it part of Flask just proper, not have these two projects.
It's going to take some time to redesign Flask to be fully AsyncIO compatible.
But yeah, the first steps are there and Quart for now is a great option.
If you really, this is interesting.
It used to be that you would think from the side of standard Python and AsyncIO will have
very few libraries that you could work with.
Now there are starting to be libraries that you want to use that only support AsyncIO.
You have a Flask application and you want to use some AsyncIO library.
So going to Quart will be a good option in that case.
And you talked about building kind of microservice-y type of things as well.
And in that world, you're waiting a lot on external systems.
And when you're mostly waiting on other things, AsyncIO is like, it's like pure magic, right?
It really shines.
Yes.
That is actually the use case.
The only one, if you ask me, that really makes sense because you can scale your little service,
tens of thousands of clients.
And since most of them are, you know, most of the time waiting, it can do that like nothing else.
It's really, really nice.
Yeah.
Super cool.
All right.
You have the last one, semi-last one.
Number 10 here is something in the same vein, but not the same.
Tell us about it.
So number 10 is, so let's say you like asynchronous programming.
You're not ready to go full-blown AsyncIO.
And you have a Flask application.
You want to take advantage of asynchronous programming.
What can you do?
What a lot of people seem to have forgotten is that there were many Async frameworks that existed from before AsyncIO.
And there are a couple of them that continue to be supported.
And they still run really well.
And Flask supports them, always supported them.
And the two that I have experience with are G-event and event-let.
And these frameworks are, they have a different philosophy compared to AsyncIO.
AsyncIO wants to make it very explicit that you are writing asynchronous code.
You even have new language keywords, Async await.
So both G-event and event-let look at this from a different side.
They try to make normal code that you're familiar with become asynchronous under the hood.
So you write the code in the way you've always done it.
And they implement or re-implement all the blocking functions in the Python standard library using asynchronous functions.
They use the same interfaces.
So these frameworks are intentionally supported by Flask.
So Flask recognizes if it's running under these frameworks.
Both are based on a package called Greenlet, which is the core technology that makes this possible.
It's a native code extension or plugin for Python that you install with pip.
And if you're running under Greenlets, then Flask makes everything work the same as if you were working with normal threads.
I personally have been using both G-event and event-let for many years on Flask applications with very little problem.
Cool. All right.
Well, that's one I didn't know about.
So that's very nice.
That's another option.
I bet it'll work great with Pyramid as well.
Yeah, probably.
You get a new implementation of sockets and threads and all those blocking functions in the standard library.
that are asynchronous.
And you call them in the same way.
Yeah, so it's way below the layer.
Yeah, like the framework wouldn't even know, right?
Right.
So you can use Flask.
You can use requests.
You know, all those libraries that do threading, networking, all those automatically become asynchronous by installing this library and using it as a server.
Very cool.
All right.
Well, that's the awesome one.
I'm going to look into that.
Now, that's our 10.
I wanted to throw just really quick and let you just riff on this one because I feel like this one is so in the wheelhouse of Flask.
And yet, I don't nearly see it spoken about enough.
Blueprints.
That is a good point.
When you're building an API, you probably, if you're doing microservices, you probably use a full application for each service.
When you're building something a little bigger than that, than a microservice, you would like to structure your application in a way that's modular.
Right.
You don't want like a 3,000 line app.py file.
Right.
Probably.
Definitely don't want that.
I don't want one.
So, Flask has this concept of blueprints, which a lot of people think there's something very complex or magical or sophisticated.
And it's really a very simple idea, which is to partition the application in different modules or packages.
And you create a blueprint, which is like a mini application that then you plug into the Flask application.
So, you create all these application subsets, which can be a collection of routes, templates, and static files.
You build these bundles.
You call them blueprints.
Each one can be a module or a package.
And then those by themselves, they do nothing.
But at some point, when you create your Flask application, you can plug them into the application.
And then at that point, they become active.
And then you can get all of those working together to form the application.
That's pretty cool.
I really like it.
So, if you had like a site and you had, let's say, seven or eight view methods that had to do with account management, right?
You would have maybe have an account module.
And there you'd have your view methods.
And instead of trying to somehow reverse past the app itself that you've created, but then also bring that back into the app.py.
It's sort of circular.
You create the blueprint.
And then you put, say, at blueprint.route instead of app.route.
And otherwise, it's basically the same.
And then you've got a much nicer participant.
It's like an application.
Yeah.
Definitely, most applications that I build, they have at least two blueprints.
One that I call main, which is the core logic.
And then one that's called auth that performs all the authentication, right?
And one nice thing about working in this modular way is that if you wrote an auth blueprint, very likely you can take it from one project to the next.
Oh, yeah.
That's a good point.
You can make it into a Python package that you can install with pip.
Some extensions, some Flask extensions are actually blueprints.
I hadn't really thought about it that way.
That's cool.
Because then you just go from your package.blueprint.
You just go app.registerroute, the package.blueprint, and boom.
It's good.
That's a really interesting way to modulize it.
Yeah.
The one that I've used does this is Flask Bootstrap, which gives you access to some nice helpers to deal with the markup and the JavaScript required to do and the forms for the bootstrap framework for the client side.
And that's a blueprint.
So when you register the extension, the extension, the only thing it does is it registers the blueprint with your application.
So it plugs into your application and then off it goes.
So it's actually a nice way to develop extensions for Flask or your own reusable packages that you want to use in your own solutions.
So many uses for blueprints.
Very cool.
All right, Miguel.
We're pretty much out of time, I think, at this point.
So those were really, really interesting.
And I think people will get a lot out of those ideas.
I'm sure most people, at least one of those is new to them, right?
Hopefully one or two.
Yes.
Yeah.
Very cool.
I know there was one new to me.
Secure the Pi was new to me.
So I got something out of it, too.
Me as well.
Awesome.
All right.
So really quick, last two questions.
If you're going to write some Python code, what editor are you using these days?
I use three editors.
So I use PyCharm sometimes.
I use Visual Studio Code sometimes.
And I use Vim sometimes.
You have to pick one.
And this is also, I'm sure it's going to disappoint a lot of people.
I think my favorite is Vim.
Okay.
And the reason is that I work a lot on remote servers.
And it's really inconvenient to set up one of the larger IDEs to work remotely.
It's sort of an annoyance.
I just want to SSH into a box and then drop my config file for Vim.
And then it works exactly like it works locally.
And Vim is our learning curve.
But once you learn it, it's actually very efficient.
And it has Python plugins that give you some of the things that you get on the more elaborate IDEs.
So I have to think that Vim is my favorite.
Also, a lot of people...
Somebody made you choose.
Yeah.
A lot of people don't like that when I do my tutorials, my tutorial videos, I use Vim.
The reason why I use Vim there is not because I like it.
It's because I know that's the least likely editor that people following my tutorials will be using.
And I want to force them to think about how to translate what I do instead of just copying every keystroke that I make.
So I use the editor that I think it's the least likely to be known by my students.
Well, interesting philosophy.
So since you brought up Vim, I have a Vim joke for you.
Okay.
How do you generate a random string?
You get a first-year computer science student to open Vim, and then you ask them to quit.
To quit.
Yeah.
It's funny.
So I did two videos that are actually very popular, showing how to set up a Flask application with PyCharm.
And then I did another one with a VS Code.
I'm going to do the same with Vim.
Yeah, you should.
It's going to be very fun.
It's probably going to generate a lot of hate as well, but I'll take it.
Yeah.
Why are the comments disabled on YouTube for this one?
I don't know.
I think people will be surprised because, of course, the very first thing that I'm going to show is how to quit, of course.
But, you know, you don't have to learn a lot of things to be productive with Vim.
Yeah, very cool.
All right.
And the notable PyPI package?
This isn't a PYPI.
Tmux is a package that I use a lot with Python and, in general, when I work on the command line.
Okay.
What does it do?
It's a terminal multiplexer.
A lot of people ask me when they see my videos.
This is another one that I get very often.
They see me, you know, happily punching keystrokes.
And suddenly, the screen divides into two.
And I get two terminals instead of one.
People don't understand what happened.
And this is Tmux.
Tmux is a very nice package.
There are actually packages on PYPI that allow you to talk to Tmux and make it even more integrated into your Python workflows.
But the package is a native utility that you install with, you know, it comes with Ubuntu.
There are Ubuntu packages or on the Mac with Brew.
On Windows and Chromebooks, you can use.
It runs perfectly well on the Linux emulation systems.
And basically allows you to create multiple terminals in the physical space of one.
And one thing that is very nice, if you have it installed in a remote server, is that when you exit the server, those terminals remain.
When you SSH back into the server the next day, all the terminals are there exactly how you left them.
I see.
So whatever you're up to is still around.
It saves all the terminals.
Yes.
Yeah.
Very cool.
So that will be my nice package to mention.
Yeah.
That's a great one.
All right.
Final call to action.
People may have been working on Flask for a while.
They want to apply some of these tips.
What do you tell them?
Something that's very important to me.
I had a lot of great stories that were a result of me sharing, you know, when I started on my blog and then conferences.
Who knows when we're going to do conferences again.
So sharing is, I think, what helped me get to where I am.
Having a job that I love.
My recommendation would be that using these tips or all the tips that you get from other sources.
And when you come up with a solution, share it.
You may think that it's something that everybody else will, you know, could easily come up with.
All right.
They already know it.
I don't need to talk about this.
I don't need to talk about it.
Well, you actually do.
There's always going to be someone who's, you know, on the same path you are, but it's, you know, a few steps behind that will benefit.
And you will help them progress in the same way that you are making progress.
So you should definitely start writing a blog or videos or tweets, you know, however, in whichever way you are comfortable.
But start sharing.
And what's going to happen is that all that value of work that you're sharing over time is going to speak for yourself.
So you will not have to take so much effort in showing yourself to prospective employers or contracting user groups, conferences when you apply to a conference.
All of that thing that you produce a little bit at a time is going to speak for you.
And it's going to be your best advocate.
That's what worked for me.
So I think everyone should.
Yeah, definitely.
And I think also it's a great way to learn, even if you don't totally know, because people will say, why are you doing that?
Why don't you use this package?
Or you could actually do this other extension or like, well, the reason I didn't do that, I didn't know.
But now I know.
Right.
Thanks for telling me.
Right.
Next time I'll do something different.
Right.
So, yeah, it's great.
All right.
Really great to catch up with you.
Thanks for coming on and sharing all these tips.
I think people will find them very useful.
Thank you so much for having me.
Bye.
Bye-bye.
This has been another episode of Talk Python to Me.
Our guest on this episode was Miguel Grinberg, and it's been brought to you by Sentry and Linode.
Take some stress out of your life.
Get notified immediately about errors in your web applications with Sentry.
Just visit talkpython.fm/sentry and get started for free.
Start your next Python project on Linode's state-of-the-art cloud service.
Just visit talkpython.fm/Linode, L-I-N-O-D-E.
You'll automatically get a $20 credit when you create a new account.
Want to level up your Python?
If you're just getting started, try my Python Jumpstart by Building 10 Apps course.
Or, if you're looking for something more advanced, check out our new async course that digs into all the different types of async programming you can do in Python.
And, of course, if you're interested in more than one of these, be sure to check out our Everything Bundle.
It's like a subscription that never expires.
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, the Google Play feed at /play, and the direct RSS feed at /rss on talkpython.fm.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now get out there and write some Python code.
I'll see you next time.