DEV Community

Cover image for Microservice in Python using FastAPI

Microservice in Python using FastAPI

Paurakh Sharma Humagain on March 19, 2020

Creating Microservices with Python Introduction to Microservices Benefits of Microservice Drawbacks of Microservice Why Microservi...
Collapse
 
cimmanuel profile image
Immanuel Kolapo

Hello @paurakhsharma , I tried using these steps to create another project but when I try inserting in the database, I get asyncpg.exceptions.DataError: invalid input for query argument $1: 213127865166 (value out of int32 range). What could be wrong? Kindly assist!
You can see this stack overflow for more https://stackoverflow.com/questions/63404139/asyncpg-exceptions-dataerror-invalid-input-for-query-argument-1-217027642536

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

I see you have already accepted the answer in StackOverflow, good luck :)

Collapse
 
sobolevn profile image
Nikita Sobolev

Thanks a lot for your introduction with FastAPI.

Consider using wemake-python-styleguide for your next FastAPI project.

It is the strictest Python linter out there. It will help you to find possible errors in your code early, show you possible refactoring opportunities, and enforce consistency across the project's codebase.

Check it out:

GitHub logo wemake-services / wemake-python-styleguide

The strictest and most opinionated python linter ever!

wemake-python-styleguide

wemake.services Supporters Build Status codecov Python Version wemake-python-styleguide


Welcome to the strictest and most opinionated Python linter ever.

wemake-python-styleguide logo

wemake-python-styleguide is actually a flake8 plugin with some other plugins as dependencies.

Quickstart

pip install wemake-python-styleguide
Enter fullscreen mode Exit fullscreen mode

You will also need to create a setup.cfg file with the configuration.

Try it online!

We highly recommend to also use:

  • flakeheaven for easy integration into a legacy codebase
  • nitpick for sharing and validating configuration across multiple projects

Running

flake8 your_module.py
Enter fullscreen mode Exit fullscreen mode

This app is still just good old flake8 And it won't change your existing workflow.

invocation results

See "Usage" section in the docs for examples and integrations.

We also support GitHub Actions as first class-citizens Try it out!

Strict is the new cool

Strict linting offers the following benefits to developers and companies:

  1. Ensures consistency - no matter who works on it, the end product will always be the same dependable code
  2. Helps avoid potential bugs - strict rules make…
Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

Sure, I will definitely have a look at it.
Thanks for sharing 🙂

Collapse
 
tadashii1417 profile image
tadashii1417

Thanks a lot for your article, really appreciate that !

But I have a little problem, when I clone the code and run "docker-compose up -d", it return
"502 Bad Gateway"

Do you know how to fix this ? I quite new to docker and nginx :v

Thanks in advance !

Collapse
 
uwevanopfern profile image
UweVanOpfern • Edited

I was facing the issue, fixed by solving this BUG, because in docker-compose.yml we used DATABASE_URI under movie-service, change it in movie-service\app\api\db.py as well, replace everywhere you have DATABASE_URL to DATABASE_URI

Collapse
 
nyancodeid profile image
Ryan Aunur Rassyid • Edited

same here

[SOLVED]
Check your docker-compose logs to see what problem came from.

docker-compose logs

Collapse
 
bagonzalo profile image
Curated

Major bugs:
(1) you need to initialize first de dabases in the "docker-compose.yml". Otherwise the services try to conect (in my case) to them without being initialize.
(2) change DATABASE_URL for DATABASE_URI here:
"""

~/python-microservices/movie-service/app/api/db.py

import os

from sqlalchemy import (Column, DateTime, Integer, MetaData, String, Table,
create_engine, ARRAY)

from databases import Database

DATABASE_URL = os.getenv('DATABASE_URL')
"""

Collapse
 
bagonzalo profile image
Curated

And thanks indeed for the post.

Collapse
 
uwevanopfern profile image
UweVanOpfern

Helped me, a lot, thanks

Collapse
 
demianbrecht profile image
Demian Brecht

This is a great, great post that touches many things. FastAPI has been on my back burner for quite some time to try out so thanks for sharing!

A question about async database queries though: Last time I looked, depending on where your database is (same network boundary as your app), you can actually incur a performance penalty by using the event loop. Do you know if that's still the case? I'm imagining a lot of work has gone into that since I last looked so maybe it's not as noticeable. That said, you'd still be freeing up the worker with the async call, so depending on your application needs, taking that performance hit may still be best.

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

I am glad that you liked it.
I am not so sure about it either.

Collapse
 
turningpro profile image
turningpro

Excellent article. Looking forward to read more of your posts.

Collapse
 
turningpro profile image
turningpro

If you can do a variation with mongodb would be much appreciated.
Not much content out there on that stack.

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

Thank you for following the article. I am glad it helped you.

Thank you for the suggestion, I will try to come up with the article for using FastAPI with Momgodb

Thread Thread
 
waldirborbajr profile image
Waldir Borba Jr

I earned another fan. Yes, please make an article FastAPI + Mongo... pls, pls plssssss

Collapse
 
coolguy1210 profile image
Aravinth Ponnusamy

Hey Paurakh, first of all, thanks for the post very helpful. I am trying to understand a few things here any guidance would be appreciated. I am a novice so, pls excuse if my questions are lame,

Q1 - I tried the example that you have given were there were only 4 fields name, plot, genres, casts
everything is fine. Now if I need to make this work for let's say mongo, I need to add 2 more fields id and year, how would you go about doing that?

fake_movie_db = [
{
'name': 'Star Wars: Episode IX - The Rise of Skywalker',
'plot': 'The surviving members of the resistance face the First Order once again.',
'genres': ['Action', 'Adventure', 'Fantasy'],
'casts': ['Daisy Ridley', 'Adam Driver']
}
]

Q2 - when I tried the same with our existing code, POST request was successful but when do a get it was not showing any of the new fields. there should be an error in this scenario?

Thanks
Aravinth

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

No, this is not a lame question. Thank you for asking the question.

To achieve this you have to add id and year to your Movie model.

e.g

class Movie(BaseModel):
    name: str
    plot: str
    genres: List[str]
    casts: List[str]
    id: str
    year: str

I hope that answers your question. Please let me know how that goes.

Collapse
 
conic profile image
isConic

This was a much needed introduction to FastAPI and possibly one of my favorites in terms of how comprehensive it was in terms of bringing in Docker, the use of Databases, and nginx configuration.

Can I request that you do something about security as well? Like authentication schemes within fast-api?

Collapse
 
plaoo profile image
Paolo Monni

Beautiful article, following what you made I created a personal "library" project. I would like to ask you if you can add the way to do the tests on the various endpoints, because following the fastapi documentation I find myself having problems with the db

Collapse
 
olegasdo profile image
olegasdo

Thank you.

Very nice article

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

Thank you 🙂

Collapse
 
nickchomey profile image
nickchomey

Thanks very much for this. Many comments are pointing out errors (and hopefully they've been fixed), but I think that's irrelevant - this article greatly demystifies this entire process for me on both a conceptual/architectural level as well as the rough details.

Collapse
 
markokhman profile image
Mark Okhman

Thanks for a great tutorial mate!
Is there any way to implement multitenancy in such a codebase?
I'm looking into this tutorial, but it seems not that obvious
mergeboard.com/blog/6-multitenancy...

Thanks!

Collapse
 
5no0p profile image
Mohammed Almustafa • Edited

Dosen't work for me

this is my docker-compose.yml:

version: '3.7'

services:
movie_service:
build: ./movie-service
command: uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
volumes:
- ./movie-service/:/app/
ports:
- 8001:8000
environment:
- DATABASE_URI=postgresql://postgres:"password"@movie_db/movie_db_dev
- CAST_SERVICE_HOST_URL=cast_service:8000/api/v1/casts/

movie_db:
image: postgres:10.14
volumes:
- postgres_data_movie:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD="password"
- POSTGRES_DB=movie_db_dev

cast_service:
build: ./cast-service
command: uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
volumes:
- ./cast-service/:/app/
ports:
- 8002:8000
environment:
- DATABASE_URI=postgresql://postgres:"password"@cast_db/cast_db_dev

cast_db:
image: postgres:10.14
volumes:
- postgres_data_cast:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD="password"
- POSTGRES_DB=cast_db_dev

nginx:
image: nginx:latest
ports:
- "8080:8080"
volumes:
- ./nginx_config.conf:/etc/nginx/conf.d/default.conf
depends_on:
- cast_service
- movie_service

volumes:
postgres_data_movie:
postgres_data_cast:

hint: "password" is my postgresql password

My nginx runing:
prnt.sc/v0qi2v

My docker:
prnt.sc/v0qind

Collapse
 
spansky profile image
Leon

An excellent article. Thanks a lot.

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

Thank you so much, I am glad that you liked it 😊

Collapse
 
mpavlov profile image
Marat Pavlov

Thanks!
1q: why did you use venv instead pipenv? I saw your previous articles and you use pipenv there

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

I think people are more familiar with venv instead fo pipenv so I choose venv.. But you can use pipenv instead, if you like it 🙂

Collapse
 
minchulkim87 profile image
Min

Wow. Thank you so much! I was looking for something like this.

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

Awesome 😊
Let me know what you would like to see next.

Collapse
 
osema profile image
osema

wooow thank u very much bro great tuto
one thing is missing i need it fastapi oauth2

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

I am glad that you like the post. I will try to come up with an article covering it.

Collapse
 
vikram_devopsmadeeasy profile image
Kunchala Vikram

Hi @paurakhsharma , I'm getting the below error while running movies service in Windows OS:
from app.api.movies import movies
ModuleNotFoundError: No module named 'app'

Collapse
 
andrequeiroz2 profile image
Andre

Obrigado foi uma bela jornada acompanhar seu tutorial. Muito bom.

Collapse
 
lioncoding profile image
Laurent Egbakou • Edited

Very nice article !
Please, can you add Travis or GitHub actions to the project and deploy it on heroku ?
Maybe update the article too. It will be nice !

Collapse
 
paurakhsharma profile image
Paurakh Sharma Humagain

Thanks for the suggestion. I will try to come up with another article regarding deployment.

Collapse
 
uwevanopfern profile image
UweVanOpfern

Really very very useful article, thanks @paurakhsharma , we need another one for deploying as well

Collapse
 
pvssrikanth profile image
pvssrikanth

Hi ,
can i get the complete code url for this article.

I am in mid way but running few errors.

please send the complete code url

thanks

Collapse
 
vikram_devopsmadeeasy profile image
Kunchala Vikram

Hi, I'm getting the below error when running movies service. I'm on windows
from app.api.movies import movies
ModuleNotFoundError: No module named 'app'

Collapse
 
tomarnaez profile image
TomArnaez • Edited

Thanks for this. I wanted to ask what's the easiest way to define a relationship a many-to-many when using encode/database?

Collapse
 
tsemester123 profile image
Tsemester

Hello @paurakhsharma
I'm Wondering If You Are Using Eureka How Will You Go About Registering The Microservice Using py_eureka_client And Expose The JSON With A Submit Endpoint

Kindly Assist

Collapse
 
hhunng profile image
phihunng

Can you upgrade this project by adding Rabbitqm or stuffs like that, thank you so much

Collapse
 
yahiaboter profile image
yahiaboter

I have a very basic question lol, Can you tell me what's the utility of the cast_db and cast_movie ?

Collapse
 
lawandahp profile image
LawandahP

man this code has errors its not working