为何将依赖的依赖纳入requirements.txt是Python开发最佳实践?
requirements.txt Is Still a Best Practice Great question—this is a common pain point for developers, especially since managing nested dependencies can feel like a hassle when removing packages. Let’s break down why this practice remains valuable, plus how to ease the frustrations you mentioned.
1. Ensures Deterministic, Reproducible Environments
The biggest win here is consistency across every environment. If you only list your direct (first-level) dependencies, pip will resolve their nested dependencies dynamically at install time. That means:
- Your local dev setup might use version 1.2 of a transitive package
foo - A teammate’s environment could pull version 1.3 (if
fooreleased an update after you set up your project) - Production might end up with version 1.1 (if the package index has older cached versions)
These tiny version gaps can trigger subtle bugs, broken features, or even crashes that are nearly impossible to debug without uniform dependency versions. Pinning every dependency (direct and nested) in requirements.txt guarantees every environment—dev, staging, production—gets exactly the same package versions every time.
2. Catches Hidden Dependency Conflicts Early
Two of your direct dependencies might rely on conflicting versions of the same nested package. For example:
package-arequiresrequests>=2.20.0package-brequiresrequests<2.19.0
If you don’t pin nested dependencies, pip will try to resolve this conflict automatically—but its choice might break one of the packages, or fail silently. By pinning all versions upfront, you’ll catch these conflicts during development (when generating the locked requirements file) instead of in production, where fixes are far more costly and disruptive.
3. Simplifies Offline/Constrained Deployments
Many production environments don’t have direct access to PyPI. Pinning all dependencies lets you pre-download every required package (using pip download -r requirements.txt) and deploy them offline without relying on pip to resolve dependencies on the fly. This eliminates deployment failures caused by network issues, package index outages, or unexpected version changes.
Easing the Pain of Removing Dependencies
You’re absolutely right that manually maintaining a full requirements.txt can be tedious when removing packages—tracking down unused nested dependencies is a chore. But modern tooling solves this problem:
- Use pip-tools: Keep a
requirements.infile with only your direct dependencies, then runpip-compile requirements.into auto-generate a lockedrequirements.txtwith all nested dependencies. When you remove a direct dependency, updaterequirements.inand re-runpip-compile—it’ll prune unused nested dependencies automatically. - Use dependency managers like Poetry or Pipenv: These tools separate your direct dependencies (in
pyproject.tomlorPipfile) from the locked full dependency tree (inpoetry.lockorPipfile.lock), making it easy to add/remove packages without manual cleanup.
While manually editing a full requirements.txt isn’t ideal, these tools let you reap the benefits of pinned nested dependencies without the manual overhead.
内容的提问来源于stack exchange,提问作者Ludo

