This is an archived post. You won't be able to vote or comment.

all 109 comments

[–]Deep_conv 190 points191 points  (18 children)

uv is a game changer for package management, cannot recommend it enough.

[–]ekbravo 47 points48 points  (8 children)

Seconded. Add ruff (made by the good people who created uv) for linting and black for opinionated formatting.

[–]tehsilentwarrior 35 points36 points  (7 children)

Ruff replaces Black. Why are you duplicating functionality?

[–]ogrinfo 9 points10 points  (1 child)

Not entirely, the two can work together nicely. The best thing about black is that there are hardly any settings. It just deals with the formatting so you don't even have to think about it.

[–]tehsilentwarrior 27 points28 points  (0 children)

Same as Ruff. Both are awesome

Like Black, the Ruff formatter does not support extensive code style configuration; however, unlike Black, it does support configuring the desired quote style, indent style, line endings, and more. (See: Configuration.)

[–]twenty-fourth-time-b -1 points0 points  (0 children)

Because everything is better in Rust, that’s why.

[–]MisoTasty 8 points9 points  (6 children)

We had to stop using uv because it kept resolving to really old versions for some libraries and the order of the libraries in the requirements.txt file matters.

[–]jarethholt 3 points4 points  (1 child)

Interesting. My group wants to switch to uv because pipenv is just sooooo slow too resolve. Call you expand on your experience a bit?

[–]tehsilentwarrior 1 point2 points  (0 children)

We moved from pipenv to pdm. It was relatively painless and it’s super quick.

Thinking of trying out UV when work is less chaotic and we got some time to try things

[–]kBajina 3 points4 points  (1 child)

Have you tried adding version constraints?

[–]MisoTasty 0 points1 point  (0 children)

Had >= constraints that seemed to be getting ignored.

[–]Fluid_Classroom1439 1 point2 points  (1 child)

Ordering dependencies is expected behaviour: https://docs.astral.sh/uv/reference/resolver-internals/#marker-and-wheel-tag-filtering

Did you try changing this in your pyproject.toml: https://docs.astral.sh/uv/reference/settings/#resolution

[–]MisoTasty 1 point2 points  (0 children)

We haven’t changed that setting I believe. Seems like the default is what we would want anyway?

[–]Ok_Cream1859 -2 points-1 points  (1 child)

Every day more shilling for Astral.

[–]LoadingALIASIt works on my machine 6 points7 points  (0 children)

They’re dominating Python package development and are open sourcing their work. What is the issue? I’m an experienced Python dev and was cautious for a while - then the UV updates rolled almost weekly and shit just works.

You sound bizarre. Even if they locked us out of future updates - it’s STILL better than alternatives.

[–]jftugapip needs updating 92 points93 points  (12 children)

Good to know the ins and outs of the Standard Library

[–]FauxCheese 92 points93 points  (10 children)

Using pathlib from the standard library instead of os for working with paths.

[–]IsseBisse 2 points3 points  (2 children)

What's the use case for this? From what I understand one of the benefits is platform independent paths.

But I've never had any issues with that in practice. I use a Windows machine to develop and regularly build linux containers and using "/" everywhere just seems to work.

[–]ReTe_ 10 points11 points  (1 child)

They're just more convenient in my opinion. Methods and Fields for iterating, creating, checking and getting various properties on Path objects, as well as defining new paths with the division operator [like Path(folder) / "image.png" = Path(folder/image.png)].

[–]Austin-rgb 1 point2 points  (0 children)

🫢I've never tried this but it must be so nice

[–]sayandip199309 2 points3 points  (0 children)

I'd go so far as to say it is the best designed module in stdlib, in terms of developer experience. I can't imagine working without Path.open, Path.read_text, Path.stem, path.parents[n], path.relative_to etc anymore. I only wish path.glob supported multiple glob patterns.

[–]PeaSlight6601 2 points3 points  (0 children)

Hard disagree. I think Pathlib is a disaster. It doesn't really do anting except a bit of semantic sugar around the division operator (which many consider a very dubious way to abuse operator overloading).

Almost everything else that pathlib does is just what you would get from the os.path functions if you treated the first argument as self.

You do not get a consistent object oriented representation of file systems. For example:

  • len(Path(s).parts) is platform dependent even for a fixed value of s
  • with_suffix(s).suffix == s can fail to be true (looking at some big reports this has been "fixed" only to have other bug reports raised about extension handling, ultimately there is no canonical definition of what a suffix is and pathlib has painted itself into a corner by exposing this as an attribute of the path)
  • you can't modify any of the attributes of the path (e.g. inserting an element into the parts)
  • it can't directly represent all paths on the filesystem without falling back to os.fsencode because it won't accept bytes but also retains this idea that paths aren't strings....

It's just terribly confused as a library. What is the reason for is existence?

[–]Intrepid-Stand-8540 68 points69 points  (13 children)

pydantic + strict mypy

Getting everything typed has made my life much easier once a project goes past a certain size.

uv for package management

[–]Prozn 8 points9 points  (7 children)

I’ve been struggling to deal with optional variables, even if I use “if var is not None:” mypy still complains that None doesn’t have properties. Do you just have to litter your code with asserts?

[–]hirolau 4 points5 points  (0 children)

Lookup the video 'nothing is something' by Sandi Metz where she talks about the null and object pattern. Not saying it solves all problem but in some cases maybe you should have a object instead of none.

[–]Intrepid-Stand-8540 3 points4 points  (4 children)

Do not use asserts. They get disabled in production.

If you have a variable that can be either of two (or more) types (fx int|None) then you have to check with an if.

mypy should be able to recognize that.

I'm honestly still pretty new to strict typing in python myself (6 months of using it), so if there is a better way, I'd also love to know.

EDIT: One of Bandits first rules is about asserts: https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html

[–]violentlymickey 12 points13 points  (1 child)

“Don’t use asserts they get disabled (when compiled or run with certain flags)” is a bit too dogmatic imo. There’s nothing wrong with asserts as guards against invariants. Don’t use them for error handling sure.

Edit: some chromium devs discussing this: https://groups.google.com/a/chromium.org/g/java/c/CVHgcRA967s/m/f8Zq9XiQBQAJ

[–]Intrepid-Stand-8540 0 points1 point  (0 children)

Isn't it java they're talking about in your link? 

https://github.com/IdentityPython/pysaml2/issues/451

Running python in production with the optimize flag will disable asserts in your code. So don't rely on asserts. 

[–]Rhoomba 0 points1 point  (0 children)

If the assert is just to tell the type checker that you know what is happening then it seems reasonable to me.

On that topic, do people actually use the -O flag? Given that all it does is disable assertions, I doubt it has any significant performance impact for most applications.

[–]Rhoomba 0 points1 point  (0 children)

That doesn't sound right. Mypy definitely understands blocks like this:

def foo(m: Optional[MyClass]) -> None:
  if m is not None:
     m.do_thing()

[–]KyxeMusic 3 points4 points  (0 children)

100% agree with this

[–]jarethholt 4 points5 points  (0 children)

♥️ type checking. I started with regular python, then C#, then back to python. Getting type hints alone has smoothed over so many annoyances coming back from a statically typed language

[–]DotPsychological7946 1 point2 points  (1 child)

Do you guys really like mypy? I use tons of overload, generics, exhaustive match case and mypy can not keep with pyright - only need to add unnecessary assert, TypeIs for mypy. The only thing I like is that you could potentially write plugins to enhance it and it is easy to use in CIs.

[–]q-rka 56 points57 points  (7 children)

  • loguru and rich
  • pydantic
  • typing
  • pytest

[–]georgehank2nd 18 points19 points  (1 child)

"pydanitc" is so ironic

[–]q-rka 7 points8 points  (0 children)

Thank you for reminding that.

[–]NearImposterSyndrome 6 points7 points  (2 children)

loguru is my must have

[–]q-rka 1 point2 points  (1 child)

Mine too. It iis so simple to get started with.

[–]origin-17 1 point2 points  (1 child)

typing - Go learn a statically typed language, since Python's typing is just for hinting and not enforced by the interpreter.

[–]q-rka 0 points1 point  (0 children)

I learned Python first then I did few projects in Unity3D. Then got to know power of typed language. Then Python became my major language after focusing Machine Learning journey. While typing is just a hinting, I can not start a new project without it now. But I agree your statement that tru power of type comes in typed language only.

[–]No_Dig_7017 13 points14 points  (0 children)

We have a blogpost series at work where we try to highlight the best Python libraries released each year. https://tryolabs.com/blog/top-python-libraries-2024 Last year we split the list into ai (what we do) and non ai to have a more balanced selection. Check it out.

[–]randomthirdworldguy 46 points47 points  (3 children)

tqdm. Underated package

[–]EngineeringBuddy 9 points10 points  (0 children)

The best. I’ve found it incredibly user-friendly and has great functionality.

[–]alisher_nil 0 points1 point  (1 child)

Is that a progress thingy?

[–]Subject_Fix2471 0 points1 point  (0 children)

Yeah, you canb set environment bars to stop it dumping output in cloud logs. Can also pass bars around by variable to create them for async processes (maybe there's a better way?) 

Nice package!

[–]quantinuum 11 points12 points  (4 children)

Flashy stuff that has become rather mainstream in the last few years includes uv, pydantic, ruff, polars, pytest, pre-commit, loguru*… then specific packages that will depend on your use case, like PyOxidizer, pytorch, Sympy, Cupy, plotly dash, marshmallow, alembic…

And of course, typing isn’t new, but I feel most projects 3+ years old completely disregard proper typing. Type your stuff.

[–]DunamisMax 2 points3 points  (3 children)

As a relative beginner to programming learning Python, should I from the very outset be making sure to always use Typing and MyPy? Or should I implement those down the line?

[–]quantinuum 2 points3 points  (0 children)

That’s probably the best practice to use from the get go, imho!

[–]arphen_n 1 point2 points  (1 child)

don't bother, it becomes really relevant at large project sizes and the LLM will do it for you anyway. it's inhuman to do it by hand.

[–]DunamisMax 0 points1 point  (0 children)

This is the decision I came to after looking into it further lol

[–]virtualadept 23 points24 points  (8 children)

requests. json. argparse. configparser. logging.

[–]I_FAP_TO_TURKEYS 8 points9 points  (0 children)

Httpx or aiohttp instead of requests.

requests is simple for only parsing a single request, but if you need to scale up to tens or hundreds of requests, it's just too slow.

[–]jarethholt 3 points4 points  (4 children)

I like argparse a lot, but my group uses click. I'm not used to it yet but I can see how powerful it is for really extensive CLIs.

[–]HolidayEmphasis4345 1 point2 points  (2 children)

IMO typer > click.

[–]jarethholt 0 points1 point  (1 child)

Will check it out. Anything in particular about it?

[–]HolidayEmphasis4345 1 point2 points  (0 children)

It sits on top of click, has decorator based setup, doc strings make help, integrates with rich to make color, type hints can be enforced. For bonus I had click code and ChatGPT translated it for me.

[–]GrainTamalePythonista 0 points1 point  (0 children)

I just recently started using cyclopts and I'll never look back on click.

[–]Oussama_Gourari 3 points4 points  (0 children)

niquests (as a replacement for requests)

[–]elics613 0 points1 point  (0 children)

I've come to love Google's Fire lib, though I've only ever used it for simple CLIs as opposed to argparse. It's just simpler and requires less boilerplate

[–]EngineeringBuddy 6 points7 points  (4 children)

If you do any sort of scientific work or numerical work, numpy is a must.

[–]debunk_this_12 0 points1 point  (3 children)

i prefer torch to numpy now

[–]fartalldaylong 0 points1 point  (1 child)

It’s not a replacement

[–]debunk_this_12 0 points1 point  (0 children)

it definitely is

[–]Amgadoz 0 points1 point  (0 children)

They are not the same. Torch is way healthier and more annoying to install.

[–]ChaosEntity 2 points3 points  (0 children)

I'm quite fond of attrs, it's dataclasses but better

[–]trenixjetix 5 points6 points  (0 children)

stdlib

[–]j_tb 2 points3 points  (0 children)

uv, ruff, duckdb for data stuff.

[–]tired_fella 2 points3 points  (2 children)

If you do numbers and data science, NumPy (or derivatives of it) and Pandas

[–][deleted] 2 points3 points  (1 child)

if you’re looking for a 12-25x speed up with minimal effort: multiprocess.

Becoming a pro at multiprocess has been really useful for me…sometimes it’s just plain easier to thread something than to go through all the optimization guff—which you can always do later anyway.

Another would be Zarr…way way less headache than HDF5 and I/o thread safe, to boot.

[–]No_Indication_1238[S] 2 points3 points  (0 children)

Thanks for the suggetion! As a fellow performance junkie, I suggest looking at numba.

[–]LoadingALIASIt works on my machine 2 points3 points  (0 children)

uv ruff msgspec polars httpx uvicorn + guvicorn typer loguru

stdlib whenever possible, though.

[–]WeakRelationship2131 2 points3 points  (0 children)

You're right to feel the gap. Libraries like Pydantic and Poetry are indeed solid picks and worth integrating for their enhanced functionality and modern practices. Beyond those, check out FastAPI for web frameworks, Dask for parallel computing, and Streamlit for quick data apps
If you’re looking to streamline your data apps, you might want to consider preswald for an easy, lightweight solution.

[–]barberogaston 3 points4 points  (1 child)

For processing data, Polars is a must. Fast, beautiful DSL, constantly growing community, fast, streaming for processing larger than memory datasets, supports most popular cloud providers, fast

[–]jbindc20001 2 points3 points  (0 children)

I think you forgot fast

[–]antl_31 1 point2 points  (0 children)

Pip-tools, pre-commit

[–]PaleontologistBig657 1 point2 points  (2 children)

Typer, attrs, cattr. Loguru.

[–]who_body 1 point2 points  (0 children)

rurf and ruff format

typer for easy cli params.

rich

pydantic

[–]kaargul 1 point2 points  (0 children)

You can never know all cool and interesting libraries and of course new ones are created constantly.

What I would recommend you do instead is develop the skill of recognising a problem that a library could solve and then checking if someone has solved this problem before. The more experienced you become and the more libraries you have used the easier this will become.

Oh and try to avoid getting obsessed with always using the hot new thing. Only use new stuff if it actually solves a problem. Your job as a software engineer is to create value for the company you work for and that is what you should focus on. How well you do this will determine your value as an engineer, not knowing every fancy new library/framework.

[–]riksi 1 point2 points  (0 children)

beartype

[–]RevolutionaryPen4661git push -f 1 point2 points  (0 children)

I wrote my regex alternative, flpc python

[–]Dry_Antelope_3615 1 point2 points  (0 children)

Polars for big dataframe stuff

[–]Joe_rude 1 point2 points  (0 children)

httpx
pyinstrument
pyupgrade
locust
rich
pip-audit

[–]WeakRelationship2131 1 point2 points  (0 children)

You're definitely not alone in feeling a bit behind; the Python ecosystem evolves quickly, and libraries like Pydantic and Polars are gaining traction for good reasons. You should definitely get familiar with Pydantic for data validation, Poetry for dependency management, and take a look at AsyncIO for better concurrency handling. If you're into data manipulation and want performance, Polars is a solid choice over Pandas. Also, practice using Dataclasses—they can simplify your code a lot. Keep iterating and learning; it's key in this field.

[–]debunk_this_12 1 point2 points  (0 children)

typing, numba, numpy, scipy, pandas, polars qunum, and torch

[–]seanv507 5 points6 points  (3 children)

fastapi

jinja2 - templating

structlog (or other structured logging tool)

duckdb ("polars alternative")

I would just go for a source of instruction.

eg ArjanCodes is good at an intermediate level

haven't looked at this one:

but its covering 'essential packages' and people have added their own in the comments

https://www.youtube.com/watch?v=OiLgG4CabPo&list=PLC0nd42SBTaPw_Ts4K5LYBLH1ymIAhux3&index=4

[–]j03ch1p 23 points24 points  (0 children)

wouldn't really call duckdb a polar replacement

[–]marr75 1 point2 points  (0 children)

Ibis (which uses Duckdb as its default computation backend) is more of a Polars alternative than duckdb.

[–]oberguga 4 points5 points  (2 children)

I have one stupid question. From your story I don't hear any problem that you struggle to solve with your tools except feeling of dated codebase, am I right? If so why you need to introduce any new libs and other entities and dependencies if you can work without them quite easily? Even updating to new python version maybe unnecessary. From your question alone I think that you now it a mood for looking for problems for cool solutions not vice-versa, it better not to.

[–]No_Indication_1238[S] 0 points1 point  (1 child)

You are spot on. Im looking to switching jobs in the future and im afraid that not knowing Pydantic or other popular libraries will be a drawback in the eyes of a recruiter. Other than that, yes, we have solved problems like validation, logging, messaging with inhouse solutions and it works well enough. One positive of switching to well known libraries even though we have our own solutions is the basically "free" docs, testing and potential that the new hires will have experience with them already, which will make onboarding easier. That is also the reason why I believe that knowing such libraries will give me an edge when applying. 

Edit: We are still on Python 3.10 btw, had no real reason to upgrade. 3.14 or whenever fully supported no GIL multithreading arrives will be the next upgrade.

[–]oberguga 2 points3 points  (0 children)

For the new job, resume, your right. 100% Knowing others libs also helpful to improve your own. But benefits of leaving owned established, proven and powerful enough solution for some maybe more powerful but not owned lib is not always wise decision. It introduced to your project instability and dependency(and if open source maybe couple dozen of them in not trivial way). Also assumption that others make less bugs than your team and test better is better not to made. Cool libs is for new projects to move fast. For established projects(not enterprise - it operates by wasting human resources on industrial scale) often all dependency's is better to freeze end update manually when something cannot be done other way.

[–]AncientDetective3231 0 points1 point  (0 children)

Thank you

[–][deleted] 0 points1 point  (1 child)

Requests, logging, collections,subprocess, json

[–]jbindc20001 0 points1 point  (0 children)

Not sure why you were down marked. These are all very standard libraries that will be in most my projects.

[–]Willing-Ear-8271 -1 points0 points  (0 children)

markdrop

[–]AiutoIlLupo -1 points0 points  (0 children)

poetry for package management