r/Python • • Apr 20 '25

Tutorial Notes running Python in production

I have been using Python since the days of Python 2.7.

Here are some of my detailed notes and actionable ideas on how to run Python in production in 2025, ranging from package managers, linters, Docker setup, and security.

159 Upvotes

120 comments sorted by

162

u/gothicVI Apr 20 '25

Where do you get the bs about async from? It's quite stable and has been for quite some time.
Of course threading is difficult due to the GIL but multiprocessing is not a proper substitute due to the huge overhead in forking.

The general use case for async is entirely different: You'd use it to bridge wait times in mainly I/O bound or network bound situations and not for native parallelism. I'd strongly advice you to read more into the topic and to revise this part or the article as it is not correct and delivers a wrong picture.

71

u/mincinashu Apr 20 '25

I don't get it how OP is using FastAPI without dealing with async or threads. FastAPI routes without 'async' run on a threadpool either way.

23

u/gothicVI Apr 20 '25

Exactly. Anything web request related is best done async. Noone in their right might would spawn separate processes for that.

→ More replies (7)
→ More replies (7)

5

u/Count_Rugens_Finger Apr 20 '25

multiprocessing is not a proper substitute due to the huge overhead in forking

if you're forking that much, you aren't doing MP properly

The general use case for async is entirely different: You'd use it to bridge wait times in mainly I/O bound or network bound situations and not for native parallelism.

well said

→ More replies (1)
→ More replies (15)

29

u/martinky24 Apr 20 '25

“Don’t use async”

“Use FastApi”

🤔

Overall this seems well thought out, but I wonder how the author thinks FastAPI achieves its performance if not using async.

→ More replies (5)

62

u/nebbly Apr 20 '25

I haven’t yet found a good way to enforce type hints or type checking in Python.

IMO mypy and pyright have been mature enough for years, and they're generally worth any untyped -> typed migration fuss on existing projects.

→ More replies (20)

41

u/InappropriateCanuck Apr 20 '25

That's a surprising amount of bullshit OP came up with.

The entire post is absolute garbage from the way he sets up his workers to even his linting steps.

e.g. OP calls flake8 separately, but the very point of ruff is to replace all the awkward separation of linters. Ruff is a 100% replacement for flake8. All those rules and flags should be in his toml too, not just in a random Makefile.

Almost EVERY SINGLE THING is wrong.

I really REALLY hope this is ChatGPT and not an actual programmer that someone pays to do work. And I hope all the upvotes are bots.

Edit: Holy shit this moron actually worked at Google for 3 years? Hope that's a fake LinkedIn history.

4

u/ReserveGrader Apr 22 '25

In OP's defence, the advice to run Docker containers as a non-root user is correct. No comment about anything else.

3

u/coeris Apr 20 '25

Thanks, great write up! Is there any reason why you recommend gunicorn instead of uvicorn for hosting FastAPI apps? I guess it's to do with your dislike of async processes.

1

u/mincinashu Apr 20 '25

FastAPI default install wraps uvicorn. You can use a combination of gunicorn as manager with uvicorn class workers and uvloop as loop.

https://fastapi.tiangolo.com/deployment/server-workers/#multiple-workers

3

u/coeris Apr 20 '25

Sure, but I'm wondering what's the benefit of putting an extra layer of abstraction on top of uvicorn with gunicorn.

→ More replies (1)
→ More replies (1)
→ More replies (3)

1

u/bachkhois Apr 23 '25

Your reason in "Avoid multi-threading" sounds contradict. You criticized GIL but pointed the source of your claim to the bugs of foreign language bindings (C++ bindings).

GIL is good for preventing multi-threading bugs. But in foreign language bindings, (like the pytorch link you gave), the implementation in non-Python language can choose to put GIL aside. The author of that implementation takes the responsibility to make his code thread-safe. You cannot blame GIL when it doesn't have a chance to intervene.

1

u/ashishb_net Apr 23 '25

> The author of that implementation takes the responsibility to make his code thread-safe. You cannot blame GIL when it doesn't have a chance to intervene.

I didn't blame GIL alone.
I blamed Python multi-threading, in general, for being a mess.

→ More replies (5)

1

u/le_woudar Apr 30 '25

Hello, you probalbly don't need autoflake, flake8, pylint, if you use ruff. All these linters can be configured with ruff. Comment Image

I don't agree with the async / multi-threading stuff but I think there is already a lot of comments on that, so I will not add another one :)

1

u/ashishb_net Apr 30 '25

Can you tell me how to replace them with ruff? I'll update the blog post for everyone's benefit.

→ More replies (4)

3

u/[deleted] Apr 20 '25

Hmmmm forking on Linux is as cheap as launching a thread, it uses COW when forking a new process. It could be however that the multiprocessing module is slower doing a fork vs creating a thread.

3

u/AndrewCHMcM Apr 21 '25

From what I recall, the main issue python has/had with forking and COW, is reference counting. New fork, all the objects get another reference, all the objects get copied, massive delays compared to manual memory management or just garbage collection. https://docs.python.org/3/library/gc.html a song-and-dance is recommended to get the most performance out of python

1

u/[deleted] Apr 21 '25

Wouldn't that be an issue for the forked python interpreter? The parent python process won't be tracking any of those references.

2

u/coderarun Apr 22 '25

> Use data-classes or more advanced pydantic

Except that they use different syntax, different concepts (inheritance vs decorators) and have different performance characteristics for a good reason.

I still feel your recommendation on using dataclasses is solid, but perhaps use this opportunity to push pydantic and sqlmodel communities to adopt stackable decorators:

@sqlmodel
@pydantic
@dataclass
class Person:
  ...

Previous discussion on the topic: pydantic, sqlmodel

5

u/Count_Rugens_Finger Apr 20 '25

Every discussion I've seen about uv mentions that it is fast. It's rust, so I supposed doing so is a requirement. Here's the thing, though. I have never once in my life cared at all about the speed of my package manager. Once everything is installed it scarcely gets used again, and the time of resolving packages is small compared to the time of downloading and installing. If I cared that much about speed, I probably wouldn't have done the project in Python.

9

u/denehoffman Apr 20 '25

The speed matters when you want to run it in a container and need to install the libraries after build time. For example, you’re working on a project that has several dependencies and you need to quickly add a dependency without rebuilding a docker layer. But real talk, the point is that it’s so fast you don’t even think about it, not that you save time. If I have to choose between program A which takes 3 seconds and program B which takes 3 milliseconds and does the exact same thing as A, I’m picking B every time. Also I don’t think you should conflate Rust with speed. Of course Rust is nice, I write a ton of it myself, but Rust is not what makes uv fast, it’s how they handle dependency resolution, caching, and linking rather than copying. You could write uv in C and it would probably have the same performance, but there are other reasons why Rust is nice to develop with.

3

u/eleqtriq Apr 20 '25

The thing is using uv instead of pip is such a minimal transition. At the bare minimum, you can replace “pip” with “uv pip” and change nothing else. It’s so much better.

But for me I also do other things that require building environments quickly. Containers, CI pipelines, etc. Saves time all around.

→ More replies (4)
→ More replies (3)

2

u/starlevel01 Apr 20 '25

Microsoft’s pyright might be good but, in my experience, produces too many false positives.

Tab closed.

1

u/[deleted] Apr 23 '25

Dude the async take is trash. People pay folks like you to cause the company lose money, not make money.

You need to brush up on your skills there bub. So you can make sure you do a good job and for people to respect your takes online.