Has anyone had to choose between Mypy and Pyright? Which is "better"?
A couple years ago I was in charge of choosing between the two, and I somewhat flippantly chose Pyright because it felt a lot faster (<5 second to do 30k lines) and had an easy integration with the editors people use at work (Pylance, coc-pyright).
Later, I realized that some popular libraries we use (django, numpy) have dedicated plugins for Mypy that you can't use with Pyright. So you have to look for Pyright-friendly type stubs or roll your own.
I've generally liked Pyright (as a side note, they have super responsive maintainers - ask a question on their GH, and they usually answer within a few hours), but I've been wondering if I am missing out with Mypy.
At least today, my experience is that Pyright is faster, flags more issues, provides better error messages, and (alas for Mypy) has fewer bugs. I hope this will change over time as Mypy matures, but there you have it.
When using Pyright in large Django projects, it's helpful to add explicit type annotations in a number of places (like reverse relations in Models) but I've found this tends to improve the clarity of the resulting code anyway.
Ruff is not a replacement for black[^1]. It's also currently complementary to pylint, not a replacement[^2]. I still use those tools with ruff.
Further, out of the box, ruff doesn't even replace isort. You have to specifically enable it to sort imports (`I`)[^3].
I personally think that ruff's defaults are much too conservative. I configure it with `ALL` and then ignore the rules I don't want. I _want_ upgrades of ruff which add new rules to find new things. I'll never know about the new rules if I have to follow its development. I fully expect `pre-commit autoupdate` to cause me some pain after I run it, and that's okay. Linters adding new rules are usually helping me make my code cleaner.
What does your pyproject.toml (or equivalent) look like? Which linters, formatters, and similar tools do you consider essential to your Python development workflow?
It is much better written, much more correct, has fewer bugs, and it is the default in VSCode so less friction to set up.
In my experience it isn't hugely faster so I wouldn't say that is a big factor. The main benefit is that it is just very correct and has very few bugs (and when there are bugs they are fixed very quickly).
I would avoid Mypy if at all possible. I once tried to fix a bug in it and the codebase was very very hairy. Partly that's because it predates official type hinting support, and partly because it supports a load of hacks to allow incorrect types. Sometimes even the way you write the type affects how it is interpreted (e.g. `a # type: foo` is different to `a: foo`).
The only times I would choose Mypy is if you really need one of those plugins you mentioned, or if you are adding types to a legacy codebase and can't face seeing how bad it really is.
Why would a typechecker written in rust be able to implement a different logic than one written in any other language?
And one written in python could just use python for the grammar so it would have the advantage of always loading the code the same exact way as python does.
We started with Mypy for thr colour-science.org projects but Pyright is so much faster that it is hard to look back. We have no particular issue with Numpy. As you pointed out the devs, especially Eric Traut, are really responsive.
When I took an "intro to programming for scientists" type course in early 2010s, it was taught in Ruby. This was at the height of ROR's popularity, and the instructor must have been curious about Ruby.
So Ruby became my first language, and for a year after taking the course I did all my scripting in Ruby. There was nobody around me (a lab full of C and Fortran coders) to tell me otherwise. Eventually, I switched to... MATLAB, and a couple years later to Python.
And in 2023, I don't remember a lick of Ruby. But I remember it was fun to code in it.
> It's still one of the most popular languages for web development.
But is it? Stats on major job boards such as Indeed show a steep decline in recent years. There are consistently twice as many Django/Flask roles listed compared with Rails. Node is the most popular but Spring, ASP.Net and PHP occupy the next level below Node.
> Use celery immediately if you have any "long lived" tasks such as email
Hey, quick question from a relative newbie who is currently trying to solve this exact problem.
Besides Celery, what are good options for handling long-running requests with Django?
I see 3 options:
- Use Celery or django Q to offload processing to worker nodes (how do you deliver results from the worker node back to the FE client?)
- Use a library called django channels that I think supports all sorts of non-trivial use cases (jobs, websockets, long polling).
- Convert sync Django to use ASGI and async views and run it using uvicorn. This option is super convoluted based on this talk [0], because you have to ensure all middleware supports ASGI, and because the ORM is sync-only, so seems like very easy to shoot yourself in the foot.
The added complication, like I mentioned, is that my long-running requests need to return data back to the client in the browser. Not sure how to make it happen yet -- using a websocket connection, or long polling?
Sorry I am ambushing you randomly in the comments like this, but it sounds like you know Django well so maybe you have some insights.
Use anything except Celery, is my vote. Even if that "anything" is something you roll yourself.
Celery is mature, but has bitten me more than anything else.
For scheduling, there are many libraries, but it's good to keep this separate from Celery IMO.
For background tasks, I think rolling your own solution (using a communication channel and method tailored to your needs) is the way to go. I really do at this point.
It definitive is not using async, I think that will bite you and not be worth the effort.
Django ORM has supported async syntax for some time now, and it can work fully async starting with Django 4.2 (and psycopg3). There are still a few rough edges (such as not being able to access deferred attributes from async contexts) but there are workarounds.
I usually use `asyncio.create_task` from async views for small, non-critical background tasks. Because they run in a thread you will lose them if the service crashes (or Kubernetes decides to restart the pod), but that's fine for some use cases. If you need persistency use Celery or something similar.
Django combined with an async-ready REST framework such as Django Ninja is very powerful these days.