I spent many years as a senior eng on a release team, and my number one piece of advice is that you should use a system that allows you to specify your actual requirements in a flexible way and then compiles that into a full 100% hard-pinned and compatible dependency list of packages that will need to be in the deployed environment. This is built-in to both uv and poetry as export functionality, but is easy to accomplish even if you are just using requirements.txt and pip.
For example, specify your packages in a file named requirements.in (instead of the normal requirements.txt), and only specify the actual packages that are imported into your application code. You can specify and specific version restrictions on these packages as usual.
Then (after pip install pip-tools) you can compile that requirements.in file into a requirements.txt that will contain not just your specified dependencies, but also the hard-pinned versions of all transitive dependencies used by your dependencies. This is so critical, I can’t tell you the number of times I’ve seen an application break even when a user has fully hard-pinned all of their main dependencies but an issue occurred in an un-pinned transitive dep.
Here’s a real world example:
Deps specified in requirements.in:
And compiled into a full requirements.txt:
When you need to add a dependency, or are ready to upgrade to new versions, you simply do so and re-test the application. In between those times however you know you can reliably re-build the environment, deploy it, or otherwise ship it off and have a (mostly) reliably ability to re-deploy without unexpected changes.
Example of exactly how this file gets updated in this particular repo, using a pyinvoke task
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.