Generating a requirements.txt file on Ubuntu is a fundamental skill for Python developers, ensuring that project dependencies are documented, shareable, and reproducible across different environments. Whether you are preparing a project for deployment, sharing code with a team, or setting up a Continuous Integration pipeline, knowing how to create a precise and clean dependency list saves countless hours of debugging version conflicts. This guide covers the standard methods, advanced tools for precision, and best practices for managing your Python dependencies on Ubuntu.
Understanding the Purpose of requirements.txt
Before diving into the commands, it is important to understand why this file matters. A requirements.On the flip side, txt file acts as a manifest listing the Python packages your project needs to run. It allows anyone—or any automated server—to recreate your exact environment using a single command: pip install -r requirements.txt Easy to understand, harder to ignore. Which is the point..
On Ubuntu, where system packages (managed by apt) and Python packages (managed by pip) often intersect, maintaining a clean separation via virtual environments is critical. Generating the requirements file from within an activated virtual environment ensures you capture only the packages your project actually uses, excluding system-level libraries or global packages installed for other projects Small thing, real impact..
Quick note before moving on.
Method 1: The Standard pip freeze Approach
The most common way to generate this file is using the built-in pip freeze command. This outputs all installed packages in the current environment in a format compatible with pip install Simple, but easy to overlook..
Step-by-Step Execution
- Open your terminal (Ctrl+Alt+T).
- figure out to your project directory:
cd /path/to/your/project - Activate your virtual environment. If you haven't created one yet, do so now:
Note: Your terminal prompt should change to showpython3 -m venv venv source venv/bin/activate(venv)indicating the environment is active. - Install your project dependencies (if you haven't already).
- Run the freeze command and redirect output to the file:
pip freeze > requirements.txt
Verifying the Output
Check the generated file to ensure it looks correct:
cat requirements.txt
You should see a list formatted like package-name==version, for example:
Django==4.That's why 2. So 7
requests==2. That's why 31. Because of that, 0
psycopg2-binary==2. 9.
**Pros:** Simple, built-in, requires no extra tools.
**Cons:** Captures *everything* in the environment, including transitive dependencies (dependencies of your dependencies) and potentially packages installed globally if you forgot to activate your venv. This leads to "dependency bloat" and potential version locking conflicts on different architectures.
## Method 2: Using `pipreqs` for Project-Specific Requirements
If you want a cleaner file that lists only the top-level packages your code actually imports (ignoring sub-dependencies), `pipreqs` is the superior tool. It scans your `.py` files for import statements and maps them to installed packages.
### Installation and Usage
1. **Install pipreqs** (preferably inside your virtual environment):
```bash
pip install pipreqs
```
2. **Run it against your project root**:
```bash
pipreqs /path/to/your/project
```
To force overwrite an existing file:
```bash
pipreqs --force /path/to/your/project
```
To save to a specific filename:
```bash
pipreqs --savepath requirements.txt /path/to/your/project
```
### Why Choose `pipreqs`?
* **Cleanliness:** It produces a minimal list (e.g., just `requests` instead of `requests`, `urllib3`, `certifi`, `charset-normalizer`, `idna`).
* **Portability:** It makes the `requirements.txt` more portable across operating systems. Sub-dependencies often have OS-specific wheels (like `psycopg2-binary` vs `psycopg2`); letting `pip` resolve the sub-dependencies during install on the target machine is often safer.
* **Detection of Missing Imports:** It warns you if you import a library that isn't installed in the current environment.
## Method 3: Modern Dependency Management with `pip-tools`
For professional workflows requiring deterministic builds and secure supply chains, `pip-tools` is the industry standard on Ubuntu. In real terms, it introduces a two-file workflow: `requirements. In practice, in` (your abstract inputs) and `requirements. txt` (the compiled, pinned output with hashes).
### Workflow
1. **Install the tool**:
```bash
pip install pip-tools
```
2. **Create a `requirements.in` file** listing only your direct dependencies, optionally with loose version specifiers:
```text
# requirements.in
django>=4.2,<5.0
requests
psycopg2-binary
```
3. **Compile the locked requirements**:
```bash
pip-compile requirements.in
```
This generates a `requirements.txt` containing every transitive dependency, pinned to a specific version, and crucially, **cryptographic hashes** for security verification.
4. **Install the compiled requirements**:
```bash
pip-sync requirements.txt
```
`pip-sync` ensures your environment matches the file *exactly*—installing missing packages, upgrading/downgrading existing ones, and **uninstalling packages not in the file**.
### Advantages for Ubuntu Deployments
* **Reproducibility:** Hashes prevent supply chain attacks and ensure the bits you download today are identical to the bits downloaded next month.
* **Conflict Resolution:** `pip-compile` resolves the dependency graph upfront, flagging version conflicts before they hit your server.
* **Multi-OS Support:** You can compile separate requirement files for development (Ubuntu) and production (Alpine/Debian slim) using `--generate-hashes` and platform constraints.
## Method 4: Exporting from Modern Project Managers (Poetry / PDM / UV)
If you use modern packaging tools like **Poetry**, **PDM**, or the extremely fast **UV**, you do not manually maintain `requirements.Which means txt`. You export it.
### Poetry
```bash
poetry export -f requirements.txt --output requirements.txt --without-hashes
Use --with-hashes for production locking.
PDM
pdm export -f requirements -o requirements.txt --without-hashes
UV (Highly Recommended for Speed)
uv pip compile pyproject.toml -o requirements.txt
# Or if using uv's own project management:
uv export --format requirements-txt > requirements.txt
These tools manage the pyproject.toml (the modern standard per PEP 621) as the source of truth and generate requirements.txt purely as a build artifact for compatibility with older tools (like standard Docker pip install steps) Worth keeping that in mind..
Handling Ubuntu System Dependencies (The apt Factor)
A common pitfall on Ubuntu is assuming requirements.Here's the thing — txt handles everything. Many Python packages (especially data science, database drivers, and image processing libraries) rely on C libraries installed via apt.
Example: psycopg2 (PostgreSQL driver) requires libpq-dev and python3-dev. Pillow requires libjpeg-dev, zlib1g-dev, etc Worth keeping that in mind..
Best Practice: Document System Dependencies Separately
Create a system-requirements.txt or a setup.sh script alongside your Python requirements:
# system-requirements.txt (for documentation)
# Run: sudo apt-get update && sudo apt-get install -y $(cat system-requirements.txt)
python3-dev
python3-venv
libpq-dev
build-essential
libjpeg-dev
zlib1g-dev
libffi-dev
libssl-dev