Pipenv Best Practices¶
This document outlines recommended best practices for using Pipenv effectively in your Python projects. Following these guidelines will help you maintain a clean, reproducible, and secure development environment.
Project Setup¶
Directory Structure¶
Organize your project with a clear directory structure:
my_project/
├── .env # Environment variables (not in version control)
├── .gitignore # Git ignore file
├── Pipfile # Dependency declarations
├── Pipfile.lock # Locked dependencies with hashes
├── README.md # Project documentation
├── src/ # Source code
│ └── my_package/ # Your package
│ ├── __init__.py
│ └── ...
├── tests/ # Test files
│ ├── __init__.py
│ └── ...
└── docs/ # Documentation
└── ...
Virtual Environment Location¶
Consider storing the virtual environment in your project directory for easier management:
export PIPENV_VENV_IN_PROJECT=1
This creates a .venv
directory in your project, making it easier to find and manage.
Dependency Management¶
Specify Python Version¶
Always specify the Python version in your Pipfile to ensure consistency across environments:
[requires]
python_version = "3.10"
Version Constraints¶
Use appropriate version constraints based on your needs:
For applications:
Use exact versions (
==
) or compatible releases (~=
) for stabilityExample:
requests = "==2.28.1"
orrequests = "~=2.28.0"
For libraries:
Use minimum versions (
>=
) to allow compatibilityExample:
requests = ">=2.28.0"
Avoid using
*
(any version) in production code, as it can lead to unpredictable behavior
Development Dependencies¶
Keep development dependencies separate from production dependencies:
# Install production dependencies
$ pipenv install flask sqlalchemy
# Install development dependencies
$ pipenv install pytest black mypy --dev
Custom Package Categories¶
For complex projects, use custom package categories to organize dependencies:
[packages]
flask = "*"
sqlalchemy = "*"
[dev-packages]
pytest = "*"
black = "*"
[docs]
sphinx = "*"
sphinx-rtd-theme = "*"
[tests]
pytest-cov = "*"
pytest-mock = "*"
Install specific categories:
$ pipenv install --categories="docs,tests"
Lock File Management¶
Always commit both
Pipfile
andPipfile.lock
to version controlRun
pipenv lock
after changing dependencies to update the lock fileUse
pipenv install --deploy
in CI/CD and production to ensure the lock file is up-to-date
Dependency Updates¶
Regularly check for and update dependencies to get security fixes:
# Check for outdated packages
$ pipenv update --outdated
# Update all packages
$ pipenv update
For production systems, test updates thoroughly before deployment.
Security Practices¶
Vulnerability Scanning¶
Regularly scan for security vulnerabilities:
$ pipenv scan
Consider integrating this into your CI/CD pipeline.
Hash Verification¶
Pipenv automatically adds hashes to Pipfile.lock
. Use these for secure installations:
$ pipenv install --deploy
Private Packages¶
For private packages, use secure URLs and authentication:
[[source]]
name = "private"
url = "https://private-repo.example.com/simple"
verify_ssl = true
Use environment variables for credentials:
export PIP_INDEX_URL=https://${USERNAME}:${PASSWORD}@private-repo.example.com/simple
Development Workflow¶
Daily Development¶
# Pull latest changes
$ git pull
# Install dependencies
$ pipenv install --dev
# Activate environment
$ pipenv shell
# Work on code...
# Run tests
$ pytest
# Deactivate when done
$ exit # or Ctrl+D
Using run Instead of shell¶
For one-off commands, use pipenv run
instead of activating the shell:
$ pipenv run pytest
$ pipenv run python -m my_package
Environment Variables¶
Use .env
files for local configuration:
# .env
DEBUG=True
DATABASE_URL=sqlite:///dev.db
Pipenv automatically loads these when you use pipenv shell
or pipenv run
.
Important: Never commit sensitive information in .env
files to version control. Add .env
to your .gitignore
.
Deployment¶
Production Installation¶
For production deployments:
# Install only production dependencies
$ pipenv install --deploy
# Or for systems without virtualenv support
$ pipenv install --system --deploy
CI/CD Integration¶
In your CI/CD pipeline:
# Example GitHub Actions workflow
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install pipenv
run: pip install pipenv
- name: Verify Pipfile.lock
run: pipenv verify
- name: Install dependencies
run: pipenv install --dev
- name: Run tests
run: pipenv run pytest
- name: Check for security vulnerabilities
run: pipenv scan
Docker Integration¶
For containerized applications:
FROM python:3.10-slim
WORKDIR /app
# Copy dependency files
COPY Pipfile Pipfile.lock ./
# Install pipenv and dependencies
RUN pip install pipenv && \
pipenv install --system --deploy
# Copy application code
COPY . .
# Run the application
CMD ["python", "-m", "my_package"]
Collaboration¶
Onboarding New Developers¶
Make it easy for new developers to set up the project:
# Clone the repository
$ git clone https://github.com/example/project.git
$ cd project
# Install dependencies
$ pipenv install --dev
# Activate the environment
$ pipenv shell
Include these instructions in your README.md.
Handling Dependency Conflicts¶
If you encounter dependency conflicts:
Check for incompatible version constraints in your Pipfile
Try clearing the cache:
pipenv lock --clear
Consider relaxing version constraints if appropriate
Use
pipenv graph
to visualize dependencies and identify conflicts
Migrating from requirements.txt¶
If migrating from a project using requirements.txt:
$ pipenv install -r requirements.txt
Then review the generated Pipfile and adjust as needed.
Performance Optimization¶
Cache Management¶
Pipenv maintains a cache to speed up installations. If you encounter issues:
# Clear the cache
$ pipenv lock --clear
# Or set a custom cache location
$ export PIPENV_CACHE_DIR=/path/to/custom/cache
Speeding Up Development Workflow¶
For faster development iterations:
# Skip lock file generation during development
$ export PIPENV_SKIP_LOCK=1
$ pipenv install some-package
Note: Only use this during development, not in production.
Handling Large Dependency Trees¶
For projects with many dependencies:
# Increase the maximum depth for dependency resolution
$ export PIPENV_MAX_DEPTH=20
$ pipenv lock
Troubleshooting¶
Common Issues and Solutions¶
Lock file hash mismatch¶
Pipfile.lock out of date, update it with "pipenv lock" or "pipenv update".
Solution: Run pipenv lock
to update the lock file.
Dependency resolution failures¶
Could not find a version that matches package==version
Solutions:
Check for conflicting version constraints
Try
pipenv lock --clear
to clear the cacheConsider relaxing version constraints
Virtualenv creation issues¶
Failed to create virtual environment.
Solutions:
Ensure you have permissions to create directories
Try
PIPENV_VENV_IN_PROJECT=1
to create the virtualenv in the project directoryCheck that the specified Python version is available
Getting Help¶
If you encounter issues:
# Get detailed environment information
$ pipenv --support
Include this output when asking for help in issues or forums.
Advanced Usage¶
Custom Scripts¶
Define custom scripts in your Pipfile for common tasks:
[scripts]
start = "python -m my_package"
test = "pytest"
lint = "flake8 src tests"
format = "black src tests"
Run them with:
$ pipenv run start
$ pipenv run test
Integration with Other Tools¶
Pre-commit hooks¶
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: tests
name: run tests
entry: pipenv run pytest
language: system
pass_filenames: false
tox¶
# tox.ini
[tox]
envlist = py38, py39, py310
[testenv]
deps = pipenv
commands =
pipenv install --dev
pipenv run pytest
Multiple Python Versions¶
For projects that support multiple Python versions:
# Test with Python 3.8
$ pipenv --python 3.8 install --dev
$ pipenv run pytest
# Test with Python 3.9
$ pipenv --rm # Remove the current virtualenv
$ pipenv --python 3.9 install --dev
$ pipenv run pytest
Conclusion¶
Following these best practices will help you maintain a clean, reproducible, and secure Python development environment with Pipenv. Adapt these recommendations to your specific project needs and team workflows.
Remember that the key benefits of Pipenv are:
Deterministic builds through the lock file
Security through hash verification
Simplified workflow by combining virtualenv and package management
Dependency isolation for each project
By leveraging these features effectively, you can focus more on development and less on environment management.