Conf42 Open Source Showcase 2020 - Online

- premiere 5PM GMT

Intro to FastAPI

Video size:

Abstract

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. From simple code you get automatic API docs, validation, and serialization.

Your API will support open standards like OpenAPI and JSON Schema by default. And your code will have autocompletion and type checks in your editor everywhere, even for your own JSON request data. It has integrated tools to handle auth with OAuth2, a powerful but simple dependency injection system, and more. FastAPI is currently used by Microsoft, Uber, Netflix, and many others for different tools and projects.

Summary

  • Fast API highperformance, easy to learn, fast to code, ready for production. Currently being used by Microsoft, Uber, Netflix and a bunch of other organizations and application systems. Based on standards like open API, JSOn, schema of two os. The more fast API code you write, the lessapi code you actually write.
  • Fast cb application takes a body and a query parameter. Then fast API will read it from the query parameters also fast API we are declaring this as being a boolean. By using standard Python type annotations like this or this fast API is one side doing documentation for application and on the other side data serialization or data conversion.
  • Fast API is doing documentation serialization or data conversion and validation. Because we are doing all this based on type annotations, on standard Python type annotations or type hints, we get autocompletion everywhere. This is all based on Python types. So we get all these things for free.
  • One does not simply make all query parameters required because it's not very common for query parameters to be required. If you have a query parameter that is required, then just try to limit the amount of them. But if you need to make them required, you can do it as well.
  • Fast API is in the top rank for python frameworks in performance. Has a dependency injection system which allows you to do very fancy stuff like authentication, authorization, or even database session management. Just make sure that it actually makes sense before just going on with fast API.
  • Fast API is like the fast API of command lined interfaces. It's also based on Python type annotations. For bash fish Seashell Powershell think is the functional deep learning framework. If you have any questions, you can ask them on the issues in the GitHub repository.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Hello, this is an intro to FastapI. So fast API highperformance, easy to learn, fast to code, ready for production. First I am Sebastin Ramrez. I'm a developer at explosion in Kotlin, Germany. I'm actually from Colombia, in South America. That's why the accent. You can find me on GitHub, LinkedIn, Twitter. I work for explosion. Explosion are the creators of Spacey, the natural language processing toolkit for doing things like machine learning over text. Also the creators of prodigy, the data set annotation tool using active learning so you can annotate data sets for machine learning with the model being live retrained live with the annotations you create and sync the deep learning framework based on standard Python type annotations. I created Fast API and Typer. We are going to talk about Fast API, so a little bit about Fast API. It has currently 15,000 GitHub stars have been growing about 1000 stars per month. So people have been liking it. It's currently being used by Microsoft, Uber, Netflix and a bunch of other organizations and application systems. The highperformance is in the top rank for Python, and Fast API is based on standards like open API, JSOn, schema of two os. Two is what is used by Facebook, Google, GitHub, Twitter. Whenever you do a login with application x, all that is using Oauth two and FastAPI lets you build these all two things very easily or integrate with them. And because it's based on all these open standards, it's very easy to have things like automatic API documentation. This automatic API documentation user interface that you can see on the right. This comes by default with Fast API for free when you create an application using FastAPI. So when you create an application using FastAPI, it's based on standards for free. You don't have to do anything to get standards based application just because you wrote it with fast API. Now, fast API is based on Python type hints or type annotations. This is the standard way you declare types in modern Python. For example, here we're saying that name is a string or that price is a float. This is a standard python. This is not a custom syntax, this is just standard Python. And because this is the standard way to declare type annotations, we get autocompletion everywhere in the editor and type checks and type errors. We are going to see more examples of this later. The point is, these standard type annotations are what provides autocompletion in your editor. So when you write code with fast API, you get autocompletion everywhere in your code. Fast API is easy and short. So this code that you see here is a complete valid fast API application. We import from Fastapi, the class Fastapi. We create an object of this class fast API and then we use this decorator here. A decorator is something that uses this add symbol and what it does is it's using in some way the function that is below. That's what a decorator does with this add symbol. What we are doing is we're saying in our application, in our past API application, we want to handle the path. Whenever we get a request that has a URL with just the path and is using HTTP get operation or an HTTP get method, we want this function to handle that. And what we are doing is just returning a dictionary that has a message hello world. You can see that we don't have to return like some type of request or some type of class or anything like that. We just return a simple dictionary. Fast API will take care of converting this to JsON. So the more fast API code you write, the less API code you actually write because fast API gets but of the way. And then you can just focus on your business logic for your application. Now let's see a basic fastapi application. This is more or less the same we just saw before we had async def for this function. Now we have this normal def function. If you don't know how async and wait works or you don't feel comfortable with them, you can just use normal functions and fast API will do the right thing for you. So this is just the normal thing we were seeing before. Now let's add another path here. This is item and we are going to take this item id as a oauth parameter. We put it in curly braces as if it was a python form f string, like a formatted string. We just don't add the f here, but it's more or less the same syntax. And we declare this item Id as a path parameter here. And we also declare it here to receive it in our function. And we are saying that this item Id is an integer. We are also declaring this queue which is a string that by default is none. Because this queue is not in the path here, fast API will take it from the query parameters. So if our application lives at this domain sundomain.com, then when we send a request with items five, this will be handled by this function. This slash items is the same items and this five here will be the item id that we declare here that we are going to receive here as a path parameter and then we can declare the query parameter after the question mark here. So this queue equals some query. Whenever our code executes, this queue will have the value sum query. If we send the URL like this, and if we check the URL, docsfacity eight automatically generates this documentation interface for us. And we can see we have the slash items item id. We have this item Id here which is the same here, that is our required path parameter and it has to be an integer. We also have the q query parameter which is a string and has to be on the query. And this documentation interface is generated automatically by fast API for us because it's based on all these standards that we were talking about. So whenever you write an application with fast API, you just write some basic code. And good guy, fast API makes a docs user interface for your API. Now let's check a basic Fastapi app with a body. We are declaring here that we have a food class and we are using this base code thing. This is imported from pydantic. So fast API is actually based uses internally this library called pydantic that helps us do a lot of all the data handling in fastapI. And pydantic uses the standard type annotations for Python. So we are declaring that we want a name to be a string and we want ingredients to be this thing list. This list is imported from typing, which is standard Python. This typing comes from Python and this list is the standard way to declare something as a list in the type annotations. So we are saying that this ingredients is a list that should contain strings and by default it's just an empty list. Then in the code that we have here below we are saying that this goes to put slash. Now this is not a get request but a post HTTP operation and we are going to handle post requests and we declare this parameter food to be an instance of this type food class that we declared before. This is also standard Python type annotations. We have lowercase food, this is a parameter, and this title case food is the same class we declared here. And by doing this we are telling Python that this food is an instance of this class. This is just like standard Python and fast API will use it to document our web API as following. So we can see that if we go to the documentation user interface, we can see the example value that we expect to receive in the value of the request. And we are going to receive a name that should be a string and we are going to receive ingredients that should be a list with strings and this is done automatically by fast API for us because we are using this standard let's go back. This is standard type annotations and this class created using pydantic. Now let's go forward. We can actually execute queries, execute requests to our API. If we go back to the quantation as we were seeing it before, we click here and try it out and we will see that this converts to an interactive system that we can execute and send data to our live application. We are sending some food that has a name of taco ingredients is frigules, carnet, taco Shell, Savasura. So this is all valid data. We are sending that and then we receive the message preparing taco. This is the same code that we were returning. We are just receiving the right response from our application. If we go back to the code we can see that we are sending this message that is preparing food name and because we are actually receiving an instance we are not receiving a dictionary, we are receiving an instance of this class food. We can use food name to get the name that we received there. And this is in query braces because this is an f string which is the modern way in python to write formatted strings. So let's go forward. We are receiving the messages that we were expecting to receive when we interact with the user interface for the documentation of our API. So well, this is how a request body full of tacos might look like. Now let's say that we want to declare a fast cb application that takes a body and a query parameter. So we declare the pydantic model as we were doing before, and now we declare it here. This is all the same code, but we are also declaring this delivery which is a boolean by default false because this delivery is not part of the path, so it's not a path parameter and because this is a simple value, a boolean, a simple value like a string, a float. A boolean is not a complex class like this food that we created here. Then fast API will read it from the query parameters also fast API we are declaring this as being a boolean. Fast API will take care of giving us a boolean, not a string with the word false or something like that. We will receive a boolean and if we see it in the interactive documentation user interface, we can see that fast API will read that delivery query parameter that we created and we'll put it here. We'll say that this is a boolean and it should go in the query parameter because we declare it as a boolean. Then the user interface is going to be able to show us the valid values which are just true or false. And this is how we will call it if we were using it, if we were sending a request to that. So we will declare after the question mark we say delivery equals true. Now notice that this URL is just a long string and this true would actually descend as if it was a string containing the text true. But because we declare it in our code, let's go back. We declare it in our code as being a boolean. Then fast API using pydantic will take care of converting this boolean that came as a string to an actual boolean. So we are going to receive a boolean in our code. This is going to be false like this one, or true if we send it to be true. So by using standard Python type annotations like this or this fast API is one side doing documentation for application automatically, and on the other side data serialization or data conversion, we are receiving the boolean instead of a string saying true or something like that. And you don't have to put everything in the body. You can use query parameters if you need to. And there's also similar ways to declare headers, cookies and so on. Now let's say that we want to receive a very complex data shape. We want to receive a JSON array of objects in our body. So adjacent array is the equivalent of a python list, adjacent object is the equivalent of a python dictionary. So we are declaring here the same way we're using this list before, we are also going to use it here. And this list comes from the standards Python typing module. And we are saying that we are going to receive others, which is a list of food. And food is this pyramidic class we created here that has name and has ingredients. And now the code that we are doing here is very simple. It's just like some sample small application that is collecting all the ingredients and putting them together. So we create a list of ingredients and for each one of the food in orders. Orders is this thing we declared here. We are iterating for each one of the ingredients in the food ingredients. So the ingredients for this specific food, and we are adding that ingredient in lowercase to all the ingredients that we have and we just return those ingredients. So we are just collecting all the ingredients for the food orders that we received. Now if we go to the documentation user interface, we can see that it detects that we declare that this should be a list of this data shape. And we can see this is a list because we have the square braces here. This is like the example value that we will be sending. So if we want to send JSON and we want to send it inside of JSON, some JSON objects inside of JSON objects or lists or wherever, we can do anything that we want. We can declare very deeply complex, deeply nested data structures and fast API will be able to handle it all based on standard python type annotations. But up to now we have seen that the whole thing is doing documentation and serialization or data conversion for us. But what happens if we send invalid data? So let's see this one. These are square brackets. So this is a list and we declared that we're going to receive a list that's valid. The first item is this JSON object and these are all JSON objects. So that's up to now. That's valid. The first item has a name which is a string. That's valid because that's what we declared. And we have ingredients, which is a list of strings. In this case click holes, cardinal, taco Shell and Sabrosura. So this is valid. Then we have the next one which has a name, which is pizza and this is a string. So this is valid. We don't have ingredients here, but if you remember the ingredients was by default an empty list because it had a default value then it is not required. So this is actually a valid food item. Now we have the next one. This has a name, Trojan Food. This sounds weird, but up to now this is valid because this has a name and this is a string. Now we check the ingredients and the first item is salt. The salt is a string inside of the list. So this is valid up to now, but the next one is actually a JSON object that has a name and it says that it's a sneaky object. We declare that we are going to receive strings, not objects. So this is weird here. And the next one has this food name which is an old breath. But if we check what we declare that we are receiving is name not food name. A name was required and because we are not sending a name here then we are not sending a required value. And if we try to execute this then we're going to receive an error automatically and the error is going to tell us that we have invalid data. So fast API is going to validate all the data based on those type annotations automatically for us and not just will give us an error saying like, hey, the data is invalid. It will tell us exactly where the data is invalid. So here we have the details. This is a list of errors and we have two errors. The first one says that in the body, in others the index two. So let's go back. This is the index one, sorry, this is the index zero. This is the index one, and this is the index two. So somewhere in here we have an error. Let's go forward. Inside of that index two, inside of ingredients. In index one, a string type has expected. So let's go back. So we were in this object, inside of ingredients, this is index zero. In index one, which is this one, a string type was expected and we sent an object. So we have a very clear specification of where the problem is. Let's check the next error. This says that it's in index three. At name, the field was required and we didn't send it. Let's go back. This is the index three and we have a full name, but we don't have a name and the required key that we were expecting was name. So fat API is giving us this validation error automatically and is doing all that for us. Let's go back to our code. It's way back here. That means that by using these standard Python type annotations, fast API is doing documentation serialization or data conversion and validation. This is saving us like, I don't know, 50 lines of code in here, something like that. So whenever this code is executed, this code that we see all here, it's because the data is already valid. Facilities already made sure that we have valid data and we can just focus on the business logic of your application, not on handling specific errors of the data shapes that you received. Now let's go forward to where we were. So we received this nice validation error when we sent invalid data. So if we send invalid data fast API or application fast API will make that face and say, no, that's not allowed. Now, because we are doing all this based on type annotations, on standard Python type annotations or type hints, we get autocompletion everywhere. Now check this. These orders is a list of instances of this class food. So we can iterate for each one of the food in orders, and when we can iterate for each ingredient in food ingredients. So you can see we are in two for tools inside. So we are two for loops deep. And still we get autocompletion for this ingredient. So the editor will know that this ingredient is a string and we will be able to have completion for this all this because it's based on standard Python types. This will be very difficult to achieve with other tools and even other languages without using the standard Python type definitions or the standard type definitions for each specific language. So we are getting all this for free and we are also getting type checks. So the code, the editor is going to know that this ingredient is a string. And if we try to sum a string with some integer it's going to give us a nice error saying like hey, this is not a valid operation here and we're going to see this error early while we are developing our application before having to wait to run the application to see the error. Like we're going to get it right away in our editor. All because it's all based on standard Python types. Well yeah, this is all based on Python types. So we get all these things for free. Now let's say that we want to add some extra metadata. So we have this delivery query parameter here. There is a boolean. We want to add a description. We want to say this is pack for delivery. So from fast API we import this query thing and then we use it here. And before we had that the default value of delivery was false. But now we are using, instead of putting false we are using this query thing here. And because we are using this space to use this query here, we no longer have the default value here. So this query will take as the first parameter what that default value has before. So we are going to take this false here. This false means that this delivery will have a default value of false and we'd also have this additional metadata, this description park for delivery. And then if we check the documentation user interface we can see that we have the park for delivery description here for this delivery query parameter that should be a boolean and that by default is false. So now let's go back. We now take the false instead of having just false here, instead having just a simple false here we have this query thing with the description and the default value for this query parameter is going to be the first parameter of query forward to the documentation. Nice. We get that. So you now don't have to write documentation outside of your code. You don't have to keep updating some wiki somewhere with what is the API expecting to do. And the front end team that is using your API is not going to come complaining that the API is no longer working because you updated it and forgot to update the wiki because everything will live right there in the code right where it belongs describing what it should be describing. Now let's say that we want to have our required query parameters, so we have the delivery which is not required because it has a default value of false and we now add another one that is quantity because it doesn't have any default value here it's going to be required and it's going to expect an integer. So this has to be an integer and it's a required query parameter. If we check the documentation we can see that we have quantity here. It's a required query parameter that has to be an integer. If we try to execute this request here without sending a quantity, we're going to receive this error. And if we send it through code or from the command line, we will also get like one of those validation errors that we were seeing before. So this is the has that the API will make when we omit required data. Now let's say that we send valid data, so we are going to but slash and we're saying after the question mark we say the quantity is going to be equal to two. We declare that this had to be an integer and we are sending two. If we execute this request, then we are going to see the response that we were expecting. So it will work nicely as we want something to have in mind. One does not simply make all query parameters required because it's not very common for query parameters to be required and clients and or developers won't probably expect the query parameters to be required. So if you have a query parameter that is required, then just try to limit the amount of them. But if you need to make them required, you can do it as well. Now let's say that we want to add some extra validation for this quantity query parameter. We can use the same query thing that we were using before. We are going to use it here as well. And we say that this quantity, which is an integer has to be greater than zero and it has to be less than or equal to ten. So this has to be a value between zero and ten. And now notice that we now are using this equals something. So this function parameter has like quote unquote, a default value of whatever this query thing is here. But we wanted this quantity to be a required query parameter. So the same way that the one before we were using the same way that the first parameter is the actual default value. In the case of delivery, this was false. In the case of quantity we also pass as the first parameter we pass the default value. And in this case we are using three dots. These three dots is a valid python syntax. This is a valid python symbol called ellipsis. And this symbol is what we are using here to tell fast API hey, I want to use these extra things, these nice features from this query thing, but I want this quantity to not have a default value and still be required. So this is how we do it. This is actually also used by pydantic and it's actually underneath it's used using pydantic. But this is the way that we are saying that this quantity must be required. And now if we go to the documentation, we can see that the quantity is required. It's an integer. And if we send invalid data, we are going to receive one of these nice messages saying hey, ensure this value is greater than zero because we declared that it had to be greater than zero. So when we say invalid data, fast API will complain to the client and won't let the data and the code pass, won't let the data pass and won't let the code even be executed because it will just show the invalid data like the invalid data errors. But if we send valid data, then it will be all happy and work nicely as we expected. So it's protecting us from invalid data, from having to do all that handling in our internal code. Now, about performance. Fast API is in the top rank for python frameworks in performance. The blue ones here, this is a third party benchmark created by Tekkenpower. And the blue ones here are Python. The green ones are go or go lang. Go is a compiled language, so this is not a fair comparison at all because Python is interpreted, go is compiled and it should be way faster than any integrated language. But fast API and some others here are able of being even faster than some goal frameworks for APIs. So this is quite nice. Which one of these is exactly the fastest is not necessarily that relevant. You can see that they are on the same ballpark. And in fact, fast API here appears on top of ubicorn. But Ubicorn is actually the bare bones server that is running fast API. So ubiquitous, should be faster than any of these guys, and fast API is actually built on top of starlet. The key point is that you get some of the best performance available for Python frameworks, and you can see that we have here in this benchmark. It is handling 15,000 something requests per second, so it's handling over 9000 requests. Cool. Some other features. Fast API has a dependency injection system which is very simple to use, but allows you to do very fancy stuff like authentication, authorization, or even database session management. A bunch of things that you can do using the dependency injection system, and the dependency injection system is also integrated with all these standards things, so you also get documentation automatically with it. It's very simple to use and very intuitive and powerful at the same time. There are also several security utilities integrated and integrated with OAuth two, which is also integrated with the documentation interface. You will have support for websockets, for files, background tasks, easy graphql integrated templates, like a bunch of other things. What you will expect from most of the frameworks now when is not a good idea to use fast API let's say that you have a stable Django application or some other framework, and it's stable if it's stable, if you don't need to add new features, it's working perfectly and it's not even an API, then you don't need to order and don't let your compulsion to refactor to rewrite it using fast API. But something that can be done if you want to use fast API is for example, adding a layer of fast API on top of your existing application to handle the new features or new requests for some additional paths that you declare or something like that. That will be like a nice way to integrated it, or to slowly migrate to fast API if you want to, just to avoid trying to rewrite everything from scratch and delaying your projects development. Nevertheless, there are teams that have just integrated entirely to fast API and have been very happy with it. But yeah, just make sure that it actually makes sense before just going on with fast API. Now some other tools typer typer is like the fast API of command lined interfaces. So this is to create command bind applications that are running terminal. It's also based on Python type annotations. The way you write code, it is almost the same as with fast API. So you get completion type checks and everything. And the nice thing is that your users, your clients are going to get shell autocompletion in their terminal. For bash fish Seashell Powershell think is the functional deep learning framework with python type annotations that is compatible with your favorite libraries like Tensorflow or Pytorch. This is built by explosion, the company I work for. And if you like these Python type annotations and you are into deep learning, you might want to check think as well. Thank you very much. That's what I have for you. If you want to check, the documentation is here. Fast API here's the documentation for FastapI. If you have any questions, you can ask them on the issues in the GitHub repository or you can also contact me in these links. Thank you very much.
...

Sebastián Ramírez

Creator @ FastAPI

Sebastián Ramírez's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways