This talk showcases various example scenarios around the ins/outs of managing Python packages. Scenarios range from intra-package problems of how to build a package, inter-package problems of how to connect packages, to general usage/environment/setup problems that developers have a hard time debugging. For each of these scenarios, I'll highlight the pros/cons, best practices, and how to overcome the issues developers commonly face.
Some examples: - installing packages from public, local file system, git (ssh + https), and how this affects deployment procedures - handling systems with multiple Python versions or package managers - how app structures and imports can affect testability - relative vs absolute imports - virtual environments - setup scripts - package versioning (why, when, how) - how new code changes could not be taking effect (old .pyc files, or updated import not catching) - handling sub-packages/dependencies that utilize parent configuration files - working with PYTHONPATH - executing python as modules or scripts
Talk presented on Nov 18, 2017 at PyCon Canada 2017.
11. Versioning Scheme
PEP440 standard from packaging.python.org
1.2.0.dev1 # Development release
1.2.0a1 # Alpha Release
1.2.0b1 # Beta Release
1.2.0rc1 # Release Candidate
1.2.0 # Final Release
1.2.0.post1 # Post Release
15.10 # Date based release
23 # Serial release
[MAJOR].[MINOR](.[MAINTENANCE])(.[CYCLE][N])
Major - Not backwards compatible or many changes
Minor - Added functionality
Maintenance/Micro - Bug fixes (or features if long version cycle)
12. Setup.py
from setuptools import setup, find_packages
setup(
name='My Project',
version='0.1.0',
description='',
author='PERSON/COMPANY',
author_email='you@example.com',
url='https://github.com/USERNAME/REPO',
packages=find_packages(),
install_requires=[
'alembic==0.8.6',
'psycopg2==2.6.1',
'PyYAML==3.11',
'SQLAlchemy==1.0.14'
]
)
setup.py (PEP440)
python setup.py install
Install package on your local environment
python setup.py register
Reserve package name on the Python Package Index (PyPI)
python setup.py sdist
Create a source-distribution bundle
twine upload dist/*
Push your currently version to PyPI
15. Where Are My Packages?
$ python run.py
ImportError: No module named flask_sqlalchemy
$ pip install flask_sqlalchemy
$ python run.py
ImportError: No module named smtplib
$ pip install smtplib
$ python run.py
ImportError: No module named passlib
$ ... #FacePalm
17. Requirements.txt & Private Git Packages
-e git+https://github.com/MY_USER/MY_REPO.git#egg=MY_REPO # Will ask for password
-e git+ssh://git@github.com/MY_USER/MY_REPO.git#egg=MY_REPO
-e git+git://github.com/MY_USER/MY_REPO.git#egg=MY_REPO
Pip supports cloning over git, git+https, and git+ssh
-e git+ssh://git@github.com/MY_USER/MY_REPO.git@staging#egg=MY_REPO
-e git+ssh://git@github.com/MY_USER/MY_REPO.git@da39a3ee#egg=MY_REPO
Install packages from commit hash or non-master branch
If you want to add git references in setup.py, use dependency_links
21. Virtual Environments (2)
Setup
Issues?
Just delete your venv and create a fresh one
$ virtualenv ~/.venvs/X
$ source ~/.venvs/X/bin/activate
(X)$ pip install -r requirements.txt
$ rm –rf ~/.venvs/X
Clean & easy dependency
management; especially when
working on multiple projects
Why?
• Package version conflicts
• v5.0.1 != v5.3.0
• Dependency contamination
across multiple projects
• Testing dependency upgrades
22. Common Scenario
1. Some files are changed
2. The code is re-run
3. The changes don’t appear to exist or are being ignored
Potential Causes
• Using an old version of a dependency
Solution: Check which version of dependencies are currently installed (`pip freeze`)
• Using old .pyc files
Solution: Remove all .pyc files in your project
Python Ignoring New Code Changes?
23. Common .pyc conflict scenarios:
• Moved or renamed python directories
• Moved or renamed python files
• Added or removed __init__.py files
• Created a variable with the same name as a module/file
To clear out all .pyc files and start fresh, run the following:
Removing old .pyc files
$ find . -name '*.pyc' -delete