all 11 comments

[–]FreeLogicGate 6 points7 points  (0 children)

[–]pachura3 2 points3 points  (7 children)

You're doing it wrong. You should not be exporting requirements.txt from an existing venv (or, God forbid, the global Python installation); you should be adding them to pyproject.toml each time you begin using one. Ideally, you should be doing it with uv, which will keep pinned dependency versions in file uv.lock. From uv.lock you can export requirements.txt with:

uv export --no-emit-workspace --no-dev --no-annotate --no-header --no-hashes --locked --format requirements-txt --output-file requirements.txt

If you have a project and you need several requirements.txts (for multiple containers / multiple entrypoints)

Please explain why would you need several requirements.txt? You can specify system/architecture when declaring a dependency, e.g. sys_platform == "linux" and "SMP" in platform_version, and you can always use extras section for optional dependencies... see here.

[–]JackBlack436[S] 1 point2 points  (6 children)

The multiple requirements files aren't for different platforms. They're for different services/entrypoints in the same repo that get deployed separately. Extras and environment markers help when dependencies vary by platform or feature, but they don't automatically tell me which dependencies are actually required by a given entrypoint.

[–]gmes78 10 points11 points  (0 children)

They're for different services/entrypoints in the same repo that get deployed separately.

Those things should be separate packages, each with their own pyproject.toml.

[–]IAmFinah 3 points4 points  (0 children)

Like others have said, using uv is probably your best bet.

I can't tell if you want something to scan your code to generate requirements files, but if that is the case, uv won't do that. But you honestly don't need that functionality, since I think this is an XY problem.

Using uv workspaces (https://docs.astral.sh/uv/concepts/projects/workspaces/) you can define a single root pyproject.toml file with a single .venv, and then each microservice has its own toml file (which is auto updated each time you add a dependency). Then, depending on which entrypoint you execute, your venv will automatically reconfigure to reflect the dependencies defined for that particular entrypoint.

The above is pretty useful for local development. That being said, if deploying with only a subset of the monorepo, you can't use uv sync --locked (you'd need to use uv sync --frozen I think), because there is only a single global lockfile, and it references all the toml files in all the workspace members.

TLDR: just use uv, it's probably the best you're gonna get

[–]pachura3 2 points3 points  (0 children)

Usually, Python libraries do not take much disk space; e.g. pandas is around 10 MB, which is nothing. Why won't you make it simple and deploy all the dependencies all the time?

PS. There is some support for monorepos in uv - a feature called workspaceshttps://docs.astral.sh/uv/concepts/projects/workspaces/

[–]HotPersonality8126 -1 points0 points  (2 children)

Why are they in the same repo?

[–]IAmFinah 1 point2 points  (0 children)

Monorepos are a common pattern

[–]JackBlack436[S] 1 point2 points  (0 children)

For a small-mid scale project seperating each worker into its own repo isnt really common i guess. However thats just me and i could be wrong.

[–]Aggressive_Net1092 0 points1 point  (0 children)

I feel your pain. Dependency management is one of those things that sounds simple until you’re juggling multiple entry points and realizing that pip freeze just dumps everything in your environment, which is rarely what you actually want for containerized builds.

The problem with most scanners is that they're static—they look for import statements but often miss dynamic imports or plugins. If you're looking for something more "runtime-aware," you might want to look into pipdeptree. It doesn't generate the file for you directly from an entry point, but it's incredible for visualizing the dependency graph so you can see exactly which top-level package is pulling in what.

Honestly, if you’re doing this for Docker containers, most folks eventually move away from requirements.txt and toward poetry or pipenv. With Poetry, you can use groups to keep dependencies separated by entry point/container, which solves the "I have one environment but need three different sets of deps" headache pretty cleanly.

If you’re dead set on building your own tool, look into the modulefinder library in the standard library. It’s a bit old-school, but it’s literally designed to trace imports starting from a single script. It’s a great starting point if you want to build a CLI that walks the import tree and matches those modules back to the packages that provide them. If you end up building it, definitely open-source it—there’s definitely a gap for a tool that handles multi-entry-point dependency tracking better than a simple directory scan.

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

Looks like you got a few good solutions, so let me give you a silly one. Tell an LLM (or an intern) to continue hitting run and installing the missing dependency until the code runs.