Search
SE Radio guest Marcelo Trylesinski

SE Radio 624: Marcelo Trylesinski on FastAPI

Marcelo Trylesinski, a senior software engineer at Pydantic and a maintainer of open-source Python tools including Starlette and Uvicorn, joins host Gregory M. Kapfhammer to talk about FastAPI. Their conversation focuses on the design and implementation of FastAPI and how programmers can use it to create web-based APIs. They also explore how to create and deploy a FastAPI implemented in the Python programming language. Brought to you by IEEE Computer Society and IEEE Software magazine.



Show Notes

Related Episodes


Transcript

Transcript brought to you by IEEE Software magazine and IEEE Computer Society. This transcript was automatically generated. To suggest improvements in the text, please contact [email protected] and include the episode number.

Gregory Kapfhammer 00:00:18 Welcome to Software Engineering Radio. I’m your host Gregory Kapfhammer. Today’s guest is Marcelo Trylesinski, a senior software engineer at Pydantic. Along with working on data validation and cloud services at Pydantic, Marcelo is a maintainer of open-source Python projects like Starlette and Uvicorn. Both of which are frameworks that are leveraged by FastAPI that is the subject of our talk today. Marcelo, welcome to Software Engineering Radio.

Marcelo Trylesinski 00:00:49 Hey man, thank you very much. It’s great to be here.

Gregory Kapfhammer 00:00:52 Alright. Hey, I’m so glad you can join the conversation today. We’re going to be talking about FastAPI. We’re going to explore what FastAPI is, how Python programmers use it and the specific problems that it solves. I think the first appropriate question is from your vantage point, what is FastAPI?

Marcelo Trylesinski 00:01:11 FastAPI, it’s a framework that’s used to build APIs in Python. It leverage type hints and it’s very fun to develop with.

Gregory Kapfhammer 00:01:21 Okay. So you mentioned that it used something called type hints or some people call those type annotations. Can you explain why that’s one of the key features of FastAPI?

Marcelo Trylesinski 00:01:30 The thing that’s cool is about the auto-completion. So it kind of forces you to use the right types because you write on the signature of the function, you write the types that you’re going to use, like the data you receive. So you have a data validation happening there. So the type that you put it there, it’s for sure the right one.

Gregory Kapfhammer 00:01:51 So one of the things I know is that the word fast means more than one thing. So for example, the FastAPI website points out that it is fast from a high- performance perspective and that in a way it’s also fast for me as a developer who’s using FastAPI. Can you comment on why FastAPI is a web framework for building APIs that’s fast in both of those fashions.

Marcelo Trylesinski 00:02:17 So for me I always saw, I mean even if I’m the maintainer of Uvicorn, the server that makes is one of the reasons that FastAPI to be fast on my perspective, the fast is more about the user perspective. Because in any case you’re still working with Python and there are certain limitations but the idea is that since you’re leveraging the async world, you don’t need to use the threads. So you can have more tasks running in a single thread and then you have more capacity to run more tasks and that means that you can receive and process more requests and that makes the server faster I would say.

Gregory Kapfhammer 00:02:58 So we’ll talk a little bit later about the async approach that FastAPI takes. Before we dive into those technical details, can you share an example of a success story maybe like for example another open-source project or a company that uses FastAPI?

Marcelo Trylesinski 00:03:15 I know a couple of companies that use FastAPI that are like big companies. Also, they are mentioned on the first page of the documentation like as a testimonial or something. I know that Netflix has one project that’s open-source as well. I think it’s called Dispatch. If you look for Dispatch Netflix on GitHub, you’re going to find it. I think that’s the most famous one that’s open-source that is like really organized with several modules and stuff. So I would say this one. You also have as an example of not the project that it’s running but you have the full stack FastAPI that Sebastian the creator of FastAPI has just, I wouldn’t say rebranded but refactored. So it uses the latest technologist that he believes should be used with FastAPI. So those two projects I think they’re very nice. But yeah, I know also Microsoft uses on some projects I saw somewhere as well. But yeah we use at Pydantic as well.

Gregory Kapfhammer 00:04:08 Thanks for sharing those examples. We’ll link to some of those in the show notes for listeners who are interested in diving in and learning more. Now, you’ll recall I mentioned a moment ago that FastAPI is for building these web APIs and I’m aware of the fact that there are a whole bunch of different API standards like the open API standard or WSGI or ASGI. Can you help the listeners to understand what some of these various standards are and how FastAPI fits into this ecosystem?

Marcelo Trylesinski 00:04:38 Yeah, sure. So the open API standard, it’s for defining how your API looks like. So it works only with HTTP related methods. So you don’t have for example, event driven things, events happening on the, like you cannot describe them on the open API spec. So for example, FastAPI also supports web sockets, but you cannot describe them on the open API because the standard like this specification does not tell you a way to specify how a web socket looks like, but you can specify all the HTTP methods like get post, but you know, so this is one thing and but what you mentioned about the WSGI and the ASCI, they are not related with this standard. They are more about how you build the, actually it’s the interface, how you interface the server and the application. So WSGI was the Python standard for many years and it’s also, there’s a BAP about it and there’s also a package called WSGI on the standard library that you can use to test and create your WSGI applications. But the ASGI one, which is, I think, I’m not sure if it’s considered new still because by now it has 6-7 years I think? It’s from, I think from 2018 or 17 and it just defines an interface for you to write Python web frameworks, I mean the server and the application leveraging async Python. So WSGI without async, ASGI with async.

Gregory Kapfhammer 00:06:11 Thanks for that response. That was really helpful. Now you mentioned that the A in ASGI or ASGI stands for asynchronous and you mentioned Async previously. Can you develop for the listeners a little bit more, what is the meaning of asynchronous and why is that important in the context of using FastAPI?

Marcelo Trylesinski 00:06:29 If you look at how things happen sequentially, so the server gets a request, right? And then it needs to do something to send to the application. So in the WSGI world, not the ASGI, WSGI previously, you had to create a thread or use a thread if you had a thread pool and then send and I mean you process the request that you’re receiving, like you get the data and then you pass that data to the application via thread. On this new WSGI World, you’d create a task an Async task, and then you’d pass the, it’s the same process but instead of using a thread, you’re going to use a task which for one reason it’s, I’m not sure if it’s easy to code with, but your application does run really fast. When you have multiple of those running, you use far less resources.

Gregory Kapfhammer 00:07:21 Sure, that makes sense. So there’s a clear benefit to this asynchronous approach and I think this brings me to my next question. Many of our listeners are probably familiar with creating a Rest API or creating a GraphQL API and they may have used both of those previously. Does FastAPI support both of those or does it only support one? How does that work?

Marcelo Trylesinski 00:07:42 For GraphQL? It doesn’t support anymore. Some years ago, I think what three years ago, I’m not sure if it was me who deprecated and removed, but I’m sure, I think I was the one who approved the request. So we removed the support for native GraphQL, like the booting, we remove it and then we have a page on the Starlette documentation where you can see alternatives and you can integrate with it. So the way it works that FastAPI, Starlette, and other ask frameworks, they have a way for you to attach or bind new. Well, also ASGI applications so you can bind them together and then you can, well use different frameworks in your application. So for example, you can use Strawberry, which is a famous GraphQL library and you can create a Strawberry and then you can use, I don’t know exactly how you connect Strawberry ASCI you something maybe, but then you can use Strawberry with FastAPI.

Gregory Kapfhammer 00:08:43 Later in the show we’re going to talk a little bit about how a person would actually write a FastAPI in Python. But before we do that, I want to spend some time talking about how FastAPI was actually implemented. I know that FastAPI uses a bunch of different frameworks and you’ve mentioned some of them already, like for example Starlette. But I wanted to begin with something that I found really unique about FastAPI, which is that “tada tada” I get automatic API documentation. How does that actually work? Can you explain it in greater detail?

Marcelo Trylesinski 00:09:16 Actually I want to go back a bit in time before that, I’m going to tell you how the idea come to exist. So there is actually an issue for that is dates like October, 2018 FastAPI was created December, 2018. So two months after this issue. So this issue was created in Starlette where, Tom Christie, the creator of Starlette, Uvicorn and HPX Docs, all of those, he wanted to discuss about, if and how to map the schema, the open API schema in Starlette. And then Sebastian saw that, and he mentioned what he wanted for a framework, not necessarily for FastAPI because at that point FastAPI didn’t exist. And on that issue, he wrote a huge comment, it’s like really huge where you can see the ideas that FastAPI had for FastAPI at time didn’t have that name, so it didn’t have any name because it didn’t exist.

Marcelo Trylesinski 00:10:13 But then Sebastian put there that he wanted the automatic documentation. He wanted validation on the input, on the output. He wanted the features that you currently see in the current FastAPI. Also those ideas, I don’t think they changed since the beginning. I think the ideas that are written on this issue still are present on the framework. And yeah, I can also send you the link so you can share with everybody with this old issue. But you ask me about how it works in great detail. The open API generation, the schema generation, so the way it works is on each FastAPI endpoint, so you have the endpoint function and you have the signature of the function, right? So the idea is that FastAPI will inspect every endpoint function and it’ll retrieve the signature, like that’s the signature and from the signature it’ll get from the parameters and from the return statement to get those types and it’ll compute the open APIs Json schema at the end.

Marcelo Trylesinski 00:11:12 So you get each function and then you compute and then you generate the open API schema, right? One thing is that you can add some metadata and some more information. So if you know every endpoint function you have, the decorator app dot and the method there, you can add some metadata. For example, you can add the how the responses look like because for example you have an HTTP exception in the body and it’s a 404, I don’t know. And then you can write on these responses, parameter on the decorator how that looks like. Because if it’s in the body of the function, there is no way you can leverage type in. So you need to write those on the decorator. So those are also being taken into consideration in the beginning of the application. Well after computing all the information that you added on the metadata from the FastAPI class, from the API router and from the decorator and from the signature of the functions itself and it generates this open API Json and then so you have now the open API Json and what you want and what FastAPI does is to create for you the Swagger page or the Redoc page.

Marcelo Trylesinski 00:12:17 Both of them are created automatically. If you don’t change any settings, you have them out of the box in FastAPI.

Gregory Kapfhammer 00:12:23 Okay, so you mentioned it has a Swagger UI or a Redoc to be very clear, what is Swagger UI and what is Redoc? And if I was a person who was using a FastAPI, what would I see on my screen?

Marcelo Trylesinski 00:12:36 Okay. So on the Swagger, well you see a page where we document all the endpoints that FastAPI has all the endpoints, HP endpoints, let’s call it like that, not the web sockets. So you’d see multiple entries describing what method it is and the path to reach that method. And then it also defines how the base URL, how it is. And then with that information you can reach the endpoint. Also you can check the query params, the body params, the path params that you can send to the application. And on Swagger, the nice thing is that you can interact with the application so you can actually try the input and then try and see what the server sends back.

Gregory Kapfhammer 00:13:19 Yeah, thank you for that response. I have to say that’s one of my favorite features of Swagger that I can actually interact with the API directly through my web interface. I also wanted to say thank you for giving us that historical perspective before because I think that’ll help our listeners to understand a little bit more about how this FastAPI system came into existence. What I want to do quickly now is to talk about the fact that FastAPI has to perform input conversion and it also has to perform output conversion. Can you tell us a little bit more about what those two things are and how that happens in FastAPI?

Marcelo Trylesinski 00:13:57 For example, I said that you have the parameters on the endpoint function, right? So imagine you have these item class that you define two fields. For example, name and age, I could help call it person I know. But anyway, you have this class and then you send the Json, instead of the age being an integrator, then it’s a string potato. Then what’s going to happen is that the FastAPI is going to try to instantiate this item and then it’s not going to be able to, it’s going to have a validation error and then the client is going to receive a 422 processable entity and it’s going to see the response. Like, there is an error here on this field. It is supposed to be an int, but you actually send a string potato. So, and then the client is able to understand what’s wrong and then can send it the right information to the server.

Gregory Kapfhammer 00:14:48 That was really helpful since you just mentioned input validation a moment ago. Let’s dive in and talk about that in greater detail. I’m aware of the fact that FastAPI uses pydantic for input validation at the very start. Can you tell us what is pydantic?

Marcelo Trylesinski 00:15:03 Pydantic? Well, it’s a company I’m working on. We have an open-source project with the same name and the package does data validation slash parsing slash cohesion. There is a lot of discussion about what it really does in terms of the wording, like if it’s cohesion, if it’s parsing, if it’s validation. But I think Samuel, the creator, I think accepted already then name validation for it, what it does. So it’s a way that you can be sure that the type you are writing in the classes, they’re actually the types you’re writing. So it’s making sure that they’re typing is what expected at run time. That’s pretty much what it is.

Gregory Kapfhammer 00:15:44 I know one of the key features of version 2.0 of Pydantic is that it’s now implemented in Rust. Can you tell us a little bit more about how you made the decision to use Rust and then perhaps talk a little bit about the benefits associated with implementing Pydantic in Rust?

Marcelo Trylesinski 00:16:00 I can talk a bit about it, but I don’t know all the details. The decision was made before I joined the company and before I knew all the information, but yeah, I can talk a bit. So what happened differently than V1 is that right now on V2, we built a schema, I think we call it pydantic schema. And then what happens that we generate this schema and then this schema is regenerating in Rust. So every time we instantiate a pydantic class, then we go to the schema and then we validate our data, and that part of the schema is done in in Rust.

Gregory Kapfhammer 00:16:37 So the benefit of using Rust is that you see a performance improvement in FastAPI, is that correct?

Marcelo Trylesinski 00:16:44 Yes, it is correct. I can talk a bit more about performance if like there are several things that will impact the performance, but yeah, changing to V2 will increase the performance of a FastAPI application.

Gregory Kapfhammer 00:16:56 Okay. I also wanted to talk about some frameworks I know you have significant interest in and that you’re a maintainer of. So for example, FastAPI uses something called Uvicorn and Starlette. Can you tell us a little bit more, I know we mentioned ASGI servers, but if you could fit in Uvicorn to what we’ve discussed and then talk about Starlette, which you mentioned before, I think it might help our listeners to understand the bigger picture of the frameworks that FastAPI uses.

Marcelo Trylesinski 00:17:24 So once again, the specs called ASCI and Uvicorn is as server which runs applications that looks like and follow the interface of ASCI. So for example, not only FastAPI but related ASCI web frameworks. So for example Starlette, which is a web framework as well. So FastAPI, Uvicorn can run, all of them. The benefit of using Uvicorn is that it leverages the UV loop. So it’s, an event loop implementation that is faster than the one provided by the standard library. So faster than the ASCI. And it also uses HTTP tools, which is a HTTP parsing library that is a binding for, C library that right now I forgot the name, but it’s the same one that’s Node JS uses it. So node uses a binding as well and HP tools is, it’s a binding for the same C library and yeah, Uvicorn is just the web server and Starlette.

Marcelo Trylesinski 00:18:25 Oh there are also other web servers that are in in this world, but Uvicorn is by far the most famous one. There is one called Hypercorn or Hepercorn, I don’t know how Phil pronounces it, the creator, but it’s also a good implementation. The difference between those two servers is that one uses streams. So in Python you have for creating web servers, you have Protocol and the other one is with streaming. So Hypercorn is with streams. So it’s more on higher level. So that’s why Hypercorn has for example, Trio Support. Trio is another Async library that is very famous that uses a structured, how do you call it, structured programming? No structured concurrence. Yeah, structured concurrence, I think that’s the name. But then Uvicorn uses protocols which is a lower level and then that’s why it’s also one of the reasons that is fast than Hypercorn.

Marcelo Trylesinski 00:19:21 And also you asked me about Starlette, right? Starlette is a web framework that is the, provides all the web capabilities for FastAPI. So everything that is about, the first step to go back to Uvicorn. So the way it happens is like the client sends a request, Uvicorn parses the request sends to the web framework FastAPI. So everything in the middle here, it goes back to Starlette. So it goes client-Uvicorn-FastAPI. So it’s instead of directly to FastAPI, there is Starlette in the middle. It’s just that FastAPI is actually, it’s in reach from Starlette. So it’s just gets all the capabilities the Starlette has to offer.

Gregory Kapfhammer 00:20:00 That sequence of events was really helpful. I appreciate you sharing that. I wanted to ask one quick clarifying question. You mentioned a client that might be connecting to a FastAPI. I know that FastAPIs are created in Python, but is there a restriction in terms of the programming language that we use in order to interact with a running FastAPI?

Marcelo Trylesinski 00:20:23 You mean the client? No, you can use any HTTP client. In any language.

Gregory Kapfhammer 00:20:28 So the last thing that I wanted to talk about when it comes to Starlette is that I often hear people refer to Starlette as a web micro framework. What does it mean if it is a micro framework?

Marcelo Trylesinski 00:20:39 I think the idea of being a micro is that you can use any part of Starlette independently. You don’t necessarily need to use the Starlette class. You can use for example the response by itself, the response class by itself. because the response class is already a web framework, sorry application. So you can just use that part. You don’t need to use the whole Starlette, you can use pieces of Starlette. I think that’s the idea.

Gregory Kapfhammer 00:21:01 I know that many of our listeners when they hear the phrase web framework or probably going to think of in the context of Python, things like Django or Flask. Can you comment briefly how are Django and Flask connected to or different from FastAPI?

Marcelo Trylesinski 00:21:17 So I know, that for example, Flask in the beginning, Sebastian tried to, I think he also created one package that was Flask something or tried to improve that. So the idea was not to create a FastAPI in the beginning, but to improve the current applications that like web frameworks that existed at the time. If I see Flask in the point of view as a user, it’s just very similar to the develop compared to FastAPI in the terms that you use also a decorator, you define what method you have. Also lately, I think two years ago flak created the decorators that you can use the HTTP method. So before you couldn’t like for example app.ga app.put, you didn’t have that before, and I think, well I like to believe, but it seems obvious because of how popular FastAPI got.

Marcelo Trylesinski 00:22:07 But I think, I hope this is correct, that was inspired by FastAPI because before you had only app.root and then you had to put the method there. But in any case, I believe it’s very similar to develop, with Flask and FastAPI. In terms of creating the application itself, I think the difference are subtle, but they matter on the usability of the framework, like creating the application itself. Like you have the type hints on FastAPI, you have the automatic documentation, but you can also have, nowadays you have some similar packages that you can use Flask with and have those capabilities, but it’s not native. And what I noticed is that having those things, those features natively makes a huge difference from the user because then you don’t need to think much about how to get those things working. It’s just out of the box.

Gregory Kapfhammer 00:22:55 Can you give a concrete example of something that you would choose to use FastAPI to build and then in contrast, give an example of something where maybe you would instead prefer to use Django or Flask?

Marcelo Trylesinski 00:23:08 Oh, I don’t have good news here.

Gregory Kapfhammer 00:23:10 Okay.

Marcelo Trylesinski 00:23:11 I don’t think I would prefer to use the alternatives in any case. But I would know like for example, I know that you could use Django to really nicely serve static web for applications. I know that use case also, I know that people like that they all the Django RM is in the same as it’s included on the Django thing. So you have the RM, you have the How to Serve files, you have the Django CSM or something like that. You have a lot of Django things that are again native from the framework that people really like. But I am very used to the FastAPI world. So I would just use FastAPI for pretty much any use case.

Gregory Kapfhammer 00:23:52 Am I right in understanding that I would primarily use FastAPI for creating a Rest API? But if I were to build a full web application like with a graphical interface, then that might be a case in which I would pick Django. Is that a fair statement?

Marcelo Trylesinski 00:24:08 I think for me, no. But I can see people agreeing with that because again, it’s out of the box on Django, you don’t need to think much about it. Like you have even tutorials about it. You have a lot of information during the years about this specific subject like how to do that specific thing that you’re asking me. But on FastAPI, you can also serve static files just fine. You have even a static files class that you can serve what you intend to.

Gregory Kapfhammer 00:24:33 Okay, that makes sense. Thanks so much for that clarification. I really appreciate it. I want to now turn our attention to some issues connected to security. Two key words that often come up in the context of API security are authentication and authorization. And so my question is does FastAPI support both authentication and authorization?

Marcelo Trylesinski 00:24:56 So FastAPI does not handle that for you. So you need to implement the layer yourself. What it does is you can define a way for how to interpret some data that comes from the request. So for example, you have HTTP basic class, which it’s used for FastAPI to get the authorization header and then get the username and the password and it provides that to your endpoint. So you have, you use that class just to kind of parse that data for you, but it does not handle that for you. What I mean, handles that you don’t have a logic to verify that the user exists in the database. That’s the correct password. That’s something you’d have to implement yourself. There are some libraries that are available for that. I honestly haven’t used any, but I have a friend called Frankie’s and some numbers that has FastAPI users. So if you Google FastAPI users, you’re going to find it’s a 4K GitHub Star’s project. I don’t know how many users have been download a day, but he’s a very good developer. So this is one possibility as an Auth library to use with FastAPI.

Gregory Kapfhammer 00:26:05 Okay. So it sounds like it’s not that FastAPI natively supports authentication and authorization, but that there are packages that you can add on in order to make that work. Is that the right way to think about it?

Marcelo Trylesinski 00:26:18 I would say it’s the same idea as Flask. On Flask you also don’t have a way to natively do this logic. You have to implement that yourself or you have to use any third-party library to do that for you.

Gregory Kapfhammer 00:26:31 Okay. And we’ll make sure to link to the framework that you mentioned a moment ago so that our listeners can check it out.

Marcelo Trylesinski 00:26:38 Yeah. One library that I always use is Authlib.

Gregory Kapfhammer 00:26:41 Yeah, that’s a good one to bring up. Can you explain it in a little bit of greater detail?

Marcelo Trylesinski 00:26:47 It helps to do the auth logic on your application. It’s just very famous. There’s one thing that I don’t like that they’re doing for years and then I complain and then they don’t reply to me is that they use this config class from Starlette, to receive two environment variables secrets I think or something like that. I use Authlib to integrate with GitHub. I think that’s my use case or that was my use case. And then they use the config class from Starlette but that’s a feature that no one uses and it prevents me from deprecating it. So, I’m saying everybody, I don’t know who uses it to be completely fair on this, but it prevents me from acting on it because this library uses it and I really use the library.

Gregory Kapfhammer 00:27:31 I see what you’re saying. I think it’s in part making your job as a maintainer perhaps a little bit more difficult.

Gregory Kapfhammer 00:27:38 So what I want to do now is talk a little bit about how a programmer would actually design and implement and test their own FastAPI. Since we’ve already covered some of the details about how FastAPIs is implemented, I think we’re ready to launch into the next stage of our show. So can we talk a little bit, you mentioned before I’ve got to write a function that represents an endpoint. I have to have type annotations for that, and I think many of our listeners will be comfortable with that process. My next question is how do I actually deploy a FastAPI?

Marcelo Trylesinski 00:28:12 So I’m going to comment on that, but I want to for our listeners to go to the FastAPI documentation on this because there is a very good page. If you go to FastAPI, you see deployments. FastAPI Sebastian dedicated good time on writing those docs and it explains in good detail about what are your options and how to do the deployment. There are some ways that people do the deployment. Like for example, there are people that deploy only with Uvicorn. I know that one of the maintainers of Uvicorn, like the one that was previous to me now is he’s very not active, but he uses only Uvicorn with just a single process. And then he said to me, it’s been running for month, no problem, a hundred of requests, it’s all fine. He said that to me when we were drinking a beer.

Marcelo Trylesinski 00:28:56 So I was like, oh, that’s good. And then there’s also recommendation on the Uvicorn documentation, for example, to use Uvicorn with Unicorn and Gunicorn is also a web server implementation, more focus on the WSGI world, but they also have a process manager. So the idea is that you’d have the Uvicorn workers, your YUvicorn processes being managed by Gunicorn. So you can also deploy with Gunicorn and Uvicorn. And what you’ll do is that every time a Uvicorn process dies, it’s going to restart that worker, so that process, and then you’re going to always have that number of workers running. So for example, I do, I create a Gunicorn, Uvicorn server with four Uvicorn workers, and then if one dies, Gunicorn will automatically restart a new worker. So you always going to have four workers during the whole lifetime of the application.

Gregory Kapfhammer 00:29:51 So this combined approach that you’re describing now sounds like it would be beneficial because it would make your system more reliable. Is that the right way to understand it?

Marcelo Trylesinski 00:29:59 Yeah, that’s correct. But also nowadays people are using Kubernetes and very fancy technologies. So, I would say that on that world it is easy and more recommended to use Uvicorn with a single process because then you have, each pod will have one process, which is the Uvicorn process, and then that’s going to be your unit in the system and you don’t want to complexify that part with Gunicorn in the middle because then you’re going to have the process one, it’s going to be Gunicorn, and then you’re going to have multiple Uvicorn workers. It gets too complex for the need.

Gregory Kapfhammer 00:30:33 I see what you’re saying. I wanted to also talk a little bit about what a developer would do when they’re testing a FastAPI. One of the things that I’ve done is I spin up a local host server. Once I have that local host server running, can I use things like unit test or PI test in order to test my FastAPI?

Marcelo Trylesinski 00:30:54 Well, we have a test client install it and FastAPI that you can use to test your endpoints. The way it does internally is that it emulates, simulates how the networking happens, but it does not really create like you are running everything in Python there. That’s just how it happens. So that would be the way to test your FastAPI application. But also you have the test client from Starlette and you also have the test client, well the client from HTTP, which is Async client and that’s the recommended one.

Gregory Kapfhammer 00:31:27 Is there a difference between using PI test to test a regular Python function or method in a program versus testing something that comes from FastAPI?

Marcelo Trylesinski 00:31:39 I’m not sure if I understand the question.

Gregory Kapfhammer 00:31:41 So the idea is many of our listeners are probably familiar with writing a function in Python and then writing a PI test case or maybe a property based test with hypothesis. And I guess my question is how would the process for testing a FastAPI be different from what they’re normally used to for something that it’s just a regular Python function or method?

Marcelo Trylesinski 00:32:04 So the way I believe things should be when you’re developing a FastAPI application or any web application is that most of your tests are going to look very similar on which you have your entry point, which would be calling the endpoint, and you’re going to always test again unexpected output. So we’re going to call this endpoint called slash potato and you expect, I don’t know, three potatoes to be back. And then the idea that I have on how you should test this, and I don’t know if you’d want to call it unit integration, I don’t, well, I don’t care. But the idea is that you want to test something, the input and against an expected output. Doing this, trying to be like not trying to test all the functions that are in the middle, you open space for changing the internals without breaking the API and also using your efforts, your energy to test this part of the code. So my idea is you have your tests and most of them are focused on the input and output and then you are free to change and refactor the code as you want. But also if you have some important logic that you want to really unit test for example, no, that is something really important on the system that you really need to test, then you are free to create some unit tests. But the way I believe is that most of the tests on the web framework should be input, output. That’s it.

Gregory Kapfhammer 00:33:26 The strategy you’re suggesting makes a lot of sense. If there are listeners of our episode who want to learn more about designing and testing APIs, we’ll link them to Episode 387 and Episode 542 in order to get more information. Now, one of the things that I would love to do in the next phase of our show is talk with you a little bit about your experiences of maintaining packages like Starlette. Obviously, you have to think carefully about how to test your own code in Starlette and you have to think carefully about how you document and you lint all of the systems that you’re building. Can you share with our listeners some of your philosophies and strategies when it comes to designing and implementing maybe Starlette or Uvicorn or FastAPI?

Marcelo Trylesinski 00:34:13 So first I think I follow the philosophy of each project specifically. So for example, Starlette and Uvicorn are under the Encode organization, which was created by Tom and I try to follow his philosophy. What I mean by this is that I always try most of the time to, if a feature is not needed on the package and it can be a third-party package, then let’s go for it first. Let’s see how the desire for that feature is on the world? And then if it gets really a lot of attention, then we can merge the feature into the library itself. So for example, we can create a middleware in a third-party package and then if that gets a lot of users, then you can go back to Starlette and then you create a request against it and then you have that merge. So this is the first thing. But for example, pydantic is more permissive on the amount of per requests. So for example, we create this pydantic extra types, which accepts a lot of types, accepts a lot of new types to be added on the library. So it really depends on the project.

Gregory Kapfhammer 00:35:13 One of the things I noticed on the FastAPI documentation is that it specifically says that the code base is a 100% type annotated and actually its test suite has a 100% test coverage. Why might that be a goal for the people who are maintaining the FastAPI system or other open-source frameworks?

Marcelo Trylesinski 00:35:33 I think it proves something. At least I believe that, well I am a strong believer of the number a 100. Anything that is less than that, I do not think it’s a good number. I’ve heard many times on a lot of companies, people saying, oh don’t worry, we have a pretty high coverage, we have 85%. But then you start looking and actually the most important thing are not tested. So it really doesn’t matter. And I think that what I really believe is the 100% clean coverage where you aim for the 100%, you’re going to do a 100%, but you are going to proactively choose when to not have something tested. And the idea is that when you write the ignores of on those lines that you don’t want to test, well, you’re doing it that actively. So you are making sure that you don’t want to test that. So that just makes sure that the library is in a better state than it could be.

Gregory Kapfhammer 00:36:25 One of the things that I’ve learned about FastAPI is that it’s something that really enhances developer productivity. I find it incredibly easy to make an API and then get it up and running and have it deployed. What were some of the strategies that the FastAPI team developed in order to ensure that actually creating an API with FastAPI was fun and that was something that enhanced developer productivity?

Marcelo Trylesinski 00:36:52 You mean strategy?

Gregory Kapfhammer 00:36:53 Well, you might not have necessarily had a strategy per se, but in your experience, what is it about FastAPI that makes it something that enhances developer productivity and makes it so easy to get up and running and ship an API?

Marcelo Trylesinski 00:37:07 I think it’s because people care about developer experience. And when I say people, I mean the maintainers of the libraries that are related. So I think Sebastian cares a lot about dev experience. I think Samuel as well. I think I do as well. So I think putting the maintainers of those related packages in like how you see them. If you work with them, you see that like they’re bothered if something takes one more second to do or one more step, they’re just bothered about that thing. So everything is around this philosophy of doing things that may be faster but have a better developer experience.

Gregory Kapfhammer 00:37:44 Can you give a concrete example of what an enhanced developer productivity experience would look like?

Marcelo Trylesinski 00:37:51 Yeah. So for example, FastAPI has the parameters, which you have the types on it. You need to have the types on it, otherwise you’re going to have an error. So you put the right type and you are sure that’s the right information you’re going to receive from the request and then you have automatic like out completion on your ID. So that’s one thing that saves a lot of time because well you have out completion so you don’t need to think about what’s right there.

Gregory Kapfhammer 00:38:15 Yeah, that’s a really good point. And I’ve had exactly that experience myself as well. I wanted to also ask you a question about your experiences. You’ve had a lot of years invested in things like Starlette and Uvicorn and FastAPI. Have there been some aha moments or some lessons that you can pass along to other developers? Like what was something that you learned that was somewhat unexpected?

Marcelo Trylesinski 00:38:38 I learned that sometimes you need to be patient, you need to wait and see if something is really worth it feature-wise. Sometimes getting too excited, it’s a problem. People are actually more unhappy about things that change then things that continue the same, even if they are not the best thing. So when trying to improve something, you need to be careful to not break other people’s APIs and not break the current way of the way they were doing things.

Gregory Kapfhammer 00:39:08 Wow, that’s an awesome insight. Is there something that we haven’t talked about in the context of FastAPI that you think we should discuss in greater detail?

Marcelo Trylesinski 00:39:16 No, I think we’ve talked plenty. Yeah, no, it’s good.

Gregory Kapfhammer 00:39:20 Alright, so in our episode we’ve covered a lot of the key concepts associated with APIs and FastAPIs. Then we dove into how FastAPI was actually implemented and then we’ve learned some strategies for actually creating testing and deploying a FastAPI. Thank you for sharing all of those insights. I really appreciate it.

Marcelo Trylesinski 00:39:41 Thank you for having me here.

Gregory Kapfhammer 00:39:42 As a conclusion to our show, do you have a call to action for our listeners in case they want to learn more about FastAPI or get started with this framework?

Marcelo Trylesinski 00:39:52 Yeah, read the docs, the docs are amazing. Go for it.

Gregory Kapfhammer 00:39:56 Alright, I have to echo that comment. The docs are absolutely amazing. We’ll make sure to link to those in the show. So let me say again, thank you. This has really been an awesome conversation. I hope that you have enjoyed the conversation. If you’re a listener, Marcelo, thank you for being here on Software Engineering Radio.

Marcelo Trylesinski 00:40:14 Thank you very much. It was great.

Gregory Kapfhammer 00:40:16 Okay, this is Gregory Kapfhammer and I’m signing off for Software Engineering Radio. Goodbye everyone.

[End of Audio]

Join the discussion

More from this show