Tworzenie pakietów Pythona: przewodnik od rozwoju do PyPI
Zdobądź wiedzę na temat pakowania w Pythonie od kodu po wdrożenie na PyPI
Opakowanie Pythona uległo znacznym zmianom, a nowoczesne narzędzia i standardy sprawiają, że dystrybucja Twojego kodu jest łatwiejsza niż kiedykolwiek.
Ten przewodnik pokaże Ci, jak tworzyć profesjonalne pakiety Pythona i publikować je w PyPI. Jeśli jesteś nowy w Pythonie lub potrzebujesz szybkiego odniesienia, sprawdź nasz Python Cheatsheet, aby szybko nauczyć się podstaw Pythona.

Dlaczego opakowywać swój kod Pythona?
Opakowanie projektu Pythona oferuje wiele korzyści:
- Odtwarzalność: Udostępniaj kod między wieloma projektami bez kopiowania i wklejania
- Dystrybucja: Pozwól innym zainstalować Twój kod za pomocą prostego
pip install - Zarządzanie zależnościami: Jasno określ i zarządzaj zależnościami
- Wersjonowanie: Śledź wersje i utrzymuj kompatybilność wsteczną
- Standardy profesjonalne: Obserwuj najlepsze praktyki społeczności Pythona
- Dokumentacja: Struktura zachęca do odpowiedniej dokumentacji i testowania
Nowoczesna struktura pakietu Pythona
Dobrze zorganizowany pakiet powinien遵循 tej struktury:
my-package/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
├── tests/
│ ├── __init__.py
│ └── test_core.py
├── docs/
│ └── index.md
├── .github/
│ └── workflows/
│ └── publish.yml
├── pyproject.toml
├── README.md
├── LICENSE
└── .gitignore
src-layout jest teraz preferowany nad płaską strukturą, ponieważ:
- Zabiega o zapobieganie przypadkowemu importowi kodu niezainstalowanego podczas rozwoju
- Ułatwia testowanie wymuszając instalację
- Jasno oddziela kod źródłowy od innych plików projektu
Podczas organizowania wewnętrznnej struktury pakietu warto rozważyć zastosowanie zasad czystej architektury, aby zwiększyć utrzymanie i testowalność kodu. Nasz przewodnik Wzorce projektowe Pythona dla czystej architektury pokazuje zasady SOLID, iniekcję zależności i wzorce architektury warstwowej, które świetnie działają z pakietami Pythona.
Plik pyproject.toml: nowoczesna konfiguracja
pyproject.toml (PEP 518, 621) jest nowoczesnym standardem konfiguracji projektu Pythona, zastępując starszy setup.py:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mypackage"
version = "0.1.0"
description = "Świetny pakiet Pythona"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Twoje Imię", email = "you@example.com"}
]
keywords = ["przykład", "tutorial", "package"]
classifiers = [
"Status rozwoju :: 4 - Beta",
"Odbiorca :: Programiści",
"Licencja :: Zatwierdzona przez OSI :: Licencja MIT",
"Język programowania :: Python :: 3",
"Język programowania :: Python :: 3.8",
"Język programowania :: Python :: 3.9",
"Język programowania :: Python :: 3.10",
"Język programowania :: Python :: 3.11",
"Język programowania :: Python :: 3.12",
]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"black>=23.0.0",
"flake8>=6.0.0",
"mypy>=1.5.0",
]
docs = [
"sphinx>=7.0.0",
"sphinx-rtd-theme>=1.3.0",
]
[project.urls]
Homepage = "https://github.com/yourusername/mypackage"
Documentation = "https://mypackage.readthedocs.io"
Repository = "https://github.com/yourusername/mypackage"
Issues = "https://github.com/yourusername/mypackage/issues"
[project.scripts]
mypackage-cli = "mypackage.cli:main"
[tool.setuptools.packages.find]
where = ["src"]
Kluczowe sekcje konfiguracji
- build-system: Określa backend budowania (setuptools, hatchling, poetry-core, flit-core)
- project: Podstawowe metadane i zależności
- project.optional-dependencies: Dodatkowe zależności funkcji (dev, docs, testowanie)
- project.scripts: Punkty wejścia do wiersza poleceń
- tool.*: Konfiguracja specyficzna dla narzędzi (black, pytest, mypy, itp.)
Wybór backendu budowania
Setuptools (standardowy wybór)
Najbardziej powszechnie używany i kompatybilny wybór:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
Zalety: Uniwersalna kompatybilność, szeroki zestaw funkcji, duża ekosystem Wady: Większa konfiguracja, wolniejszy niż nowoczesne alternatywy
Hatchling (nowoczesny i szybki)
Lekki i wydajny nowoczesny backend:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Zalety: Szybkie budowanie, prosta konfiguracja, dobre domyślne ustawienia Wady: Mniej wtyczek niż setuptools
Poetry (wszechstronny)
Kompletna zarządzanie zależnościami i środowiskami:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "mypackage"
version = "0.1.0"
description = "Świetny pakiet Pythona"
authors = ["Twoje Imię <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
Zalety: Rozwiązywanie zależności, pliki blokujące, zintegrowany workflow Wady: Różna praca, większa powierzchnia narzędzia
Flit (minimalistyczny)
Prosty narzędzie do prostych pakietów:
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
Zalety: Ekstremalnie prosty, minimalna konfiguracja Wady: Ograniczone funkcje dla złożonych pakietów
Budowanie pakietu
Zainstaluj narzędzia budowania
# Zainstaluj nowoczesne narzędzie budowania
pip install build
# Albo dla Poetry
pip install poetry
# Albo dla Hatchling
pip install hatch
Budowanie plików dystrybucyjnych
Używając pakietu build (działa z każdym backendem):
# Wyczyść poprzednie budowania
rm -rf dist/ build/ *.egg-info
# Buduj dystrybucję źródłową i wheel
python -m build
# To tworzy:
# dist/mypackage-0.1.0.tar.gz (dystrybucja źródłowa)
# dist/mypackage-0.1.0-py3-none-any.whl (wheel)
Używając Poetry:
poetry build
Używając Hatch:
hatch build
Zrozumienie formatów dystrybucyjnych
Dystrybucja źródłowa (sdist) - .tar.gz
- Zawiera kod źródłowy i instrukcje budowania
- Użytkownicy pip budują je podczas instalacji
- Zawiera testy, dokumentację i inne pliki do rozwoju
Wheel - .whl
- Przygotowana dystrybucja binarna
- Szybka instalacja (bez kroku budowania)
- Platformowa lub czysta Pythona
- Zalecany format dystrybucyjny
Publikowanie w PyPI
Metoda 1: Ręczne przesyłanie za pomocą Twine (tradycyjna)
# Zainstaluj twine
pip install twine
# Sprawdź pakiet przed przesyłaniem
twine check dist/*
# Prześlij do TestPyPI (zalecane)
twine upload --repository testpypi dist/*
# Testuj instalację z TestPyPI
pip install --index-url https://test.pypi.org/simple/ mypackage
# Prześlij do produkcji PyPI
twine upload dist/*
Skonfiguruj poświadczenia w ~/.pypirc:
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmc...
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgENdGVzdC5weXBpLm9yZw...
Metoda 2: Publikacja zaufana (zalecana do CI/CD)
Publikacja zaufana używa OpenID Connect (OIDC) do uwierzytelniania z platform CI/CD bez przechowywania tokenów.
Konfiguracja w PyPI:
- Przejdź do ustawień projektu w PyPI
- Przejdź do sekcji “Publikacja”
- Dodaj nowego “pending publisher”
- Skonfiguruj:
- Właściciel: Twoje imię użytkownika/organizacji na GitHub
- Repozytorium: Nazwa repozytorium
- Workflow:
publish.yml - Środowisko:
release(opcjonalnie, ale zalecane)
Workflow GitHub Actions (.github/workflows/publish.yml):
name: Publish to PyPI
on:
release:
types: [published]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Store distribution packages
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: dist/
publish:
needs: build
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Download distributions
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Zalety:
- Brak tokenów API do zarządzania lub zabezpieczania
- Automatyczne uwierzytelnianie za pomocą OIDC
- Wzmacniana bezpieczeństwo poprzez reguły ochrony środowiska
- Śledzenie wszystkich publikacji
Najlepsze praktyki
1. Zarządzanie wersjami
Użyj semantycznego numerowania wersji (SemVer): MAJOR.MINOR.PATCH
# Zainstaluj narzędzie do zwiększania wersji
pip install bump2version
# Zwiększ wersję
bump2version patch # 0.1.0 -> 0.1.1
bump2version minor # 0.1.1 -> 0.2.0
bump2version major # 0.2.0 -> 1.0.0
Skonfiguruj w .bumpversion.cfg:
[bumpversion]
current_version = 0.1.0
commit = True
tag = True
[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
[bumpversion:file:src/mypackage/__init__.py]
search = __version__ = "{current_version}"
replace = __version__ = "{new_version}"
2. Uwzględnij istotne pliki
README.md: Jasne opisy projektu, instalacja, przykłady użycia LICENSE: Wybierz odpowiednią licencję (MIT, Apache 2.0, GPL, itp.) CHANGELOG.md: Dokumentuj zmiany między wersjami .gitignore: Wyklucz artefakty budowania, cache, wirtualne środowiska
3. Kompleksowe testy
# Zainstaluj zależności testowe
pip install pytest pytest-cov
# Uruchom testy z pokryciem
pytest --cov=mypackage tests/
# Wygeneruj raport pokrycia
pytest --cov=mypackage --cov-report=html tests/
Skonfiguruj w pyproject.toml:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "--strict-markers --cov=mypackage"
4. Narzędzia jakości kodu
# Formatowanie
black src/ tests/
# Lintowanie
flake8 src/ tests/
# Sprawdzanie typów
mypy src/
# Sortowanie importów
isort src/ tests/
Integruj z pre-commit hooks (.pre-commit-config.yaml):
repos:
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
5. Dokumentacja
Użyj Sphinx do dokumentacji:
# Zainstaluj Sphinx
pip install sphinx sphinx-rtd-theme
# Inicjalizuj dokumentację
cd docs
sphinx-quickstart
# Buduj dokumentację
make html
Lub użyj MkDocs dla prostszej dokumentacji opartej na Markdown:
pip install mkdocs mkdocs-material
mkdocs new .
mkdocs serve
6. Integracja ciągła
Testowanie pakietów Pythona na różnych platformach i środowiskach jest kluczowe dla niezawodności. Dla informacji na temat wydajności Pythona w różnych scenariuszach wdrażania, zobacz nasze porównanie Wydajność AWS Lambda: JavaScript vs Python vs Golang, które bada, jak Python działa w środowiskach bezserwerowych.
Kompletny workflow CI/CD (.github/workflows/ci.yml):
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run tests
run: pytest --cov=mypackage --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install black flake8 mypy
- name: Black formatting check
run: black --check src/ tests/
- name: Flake8
run: flake8 src/ tests/
- name: MyPy
run: mypy src/
Typowe pułapki i rozwiązania
Problem 1: Błędy importu po instalacji
Problem: Pakiet zainstalowany, ale importy nie działają
Rozwiązanie: Upewnij się, że struktura pakietu jest poprawna z plikami __init__.py i poprawna konfiguracja pyproject.toml:
[tool.setuptools.packages.find]
where = ["src"]
include = ["mypackage*"]
Problem 2: Brakujące zależności
Problem: Pakiet zainstalowany, ale zawodzi w czasie działania z powodu braku zależności
Rozwiązanie: Oznacz wszystkie zależności w czasie działania w pyproject.toml:
[project]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
Problem 3: Konflikty wersji
Problem: Pakiet działa w środowisku deweloperskim, ale zawodzi w środowisku produkcyjnym
Rozwiązanie: Użyj środowisk wirtualnych i określ minimalne wersje:
# Utwórz izolowane środowisko
python -m venv .venv
source .venv/bin/activate # Na Windows: .venv\Scripts\activate
# Zainstaluj w trybie edycji dla dewelopera
pip install -e ".[dev]"
Problem 4: Duży rozmiar pakietu
Problem: Pakiet zbyt długo pobiera się / instaluje
Rozwiązanie: Wyklucz niepotrzebne pliki za pomocą MANIFEST.in:
include README.md
include LICENSE
include pyproject.toml
recursive-include src *.py
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-exclude tests *
recursive-exclude docs *
Problem 5: Problemy platformowe
Problem: Pakiet działa na jednym systemie operacyjnym, ale zawodzi na innym
Rozwiązanie: Testuj na wielu platformach za pomocą macierzy budowania CI/CD (patrz przykład powyżej)
Lista sprawdzania przed publikacją
Przed publikacją pakietu w PyPI, upewnij się, że:
- Wszystkie testy przechodzą na różnych wersjach Pythona
- Kod jest sformatowany i przeszkolony
- README.md jest kompletny z przykładami
- Plik LICENSE jest uwzględniony
- Numer wersji został zaktualizowany
- CHANGELOG.md został zaktualizowany
- Zależności są poprawnie określone
- Pakiet buduje się bez błędów (
python -m build) - Pakiet został przetestowany na TestPyPI
- Dokumentacja jest aktualna
- Repozytorium Git jest oznaczone wersją
- Utworzono wydanie GitHub (dla zaufanej publikacji)
Zaawansowane tematy
Punkty wejścia i narzędzia CLI
Tworzenie interfejsów wiersza poleceń:
[project.scripts]
mypackage = "mypackage.cli:main"
Implementacja w src/mypackage/cli.py:
import click
@click.command()
@click.option('--name', default='Świat', help='Imię do powitania')
def main(name):
"""Przykładowy przykład narzędzia CLI"""
click.echo(f'Cześć, {name}!')
if __name__ == '__main__':
main()
Dla rzeczywistego przykładu tworzenia pakietów Pythona, które interagują z zewnętrznymi API, zobacz nasz przewodnik Integracja Ollama z Pythonem, który demonstruje budowanie klientów Pythona z obu integracji REST API i oficjalnej biblioteki.
Systemy wtyczek
Włącz odkrywanie wtyczek:
[project.entry-points."mypackage.plugins"]
plugin_a = "mypackage_plugin_a:PluginA"
Rozszerzenia C
Dla kodu krytycznego pod względem wydajności:
[tool.setuptools.ext-modules]
name = "mypackage._speedups"
sources = ["src/mypackage/_speedups.c"]
Pakiety przestrzeni nazw
Dla pakietów rozdzielonych w ramach wspólnego przestrzeni nazw:
[tool.setuptools.packages.find]
where = ["src"]
include = ["company.*"]
[tool.setuptools.package-data]
"company.mypackage" = ["py.typed"]
Użyteczne narzędzia i zasoby
Narzędzia do rozwoju pakietów
- cookiecutter: Szablony projektowe dla pakietów Pythona
- tox: Automatyzacja testów na różnych wersjach Pythona
- nox: Wersja elastyczna testowania (alternatywa dla tox)
- pre-commit: Framework wtyczek Git dla jakości kodu
- commitizen: Standaryzacja komunikatów commit i wersjonowania
Platformy dokumentacji
- Read the Docs: Darmowe hostowanie dokumentacji
- GitHub Pages: Hostowanie dokumentacji MkDocs lub Sphinx
- pdoc: Prosty generator dokumentacji API
Rejestry pakietów
- PyPI: Oficjalny Python Package Index (pypi.org)
- TestPyPI: Środowisko testowe (test.pypi.org)
- Anaconda.org: Dystrybucja pakietów Conda
- GitHub Packages: Hosting prywatnych pakietów
Monitorowanie i analizy
- PyPI Stats: Statystyki pobierania pakietów
- Libraries.io: Monitorowanie zależności i powiadomienia
- Snyk: Scanning bezpieczeństwa wadliwych zależności
- Dependabot: Automatyczne aktualizacje zależności
Podsumowanie
Nowoczesne opakowanie Pythona zostało zoptymalizowane pod kątem przyjazności dla deweloperów dzięki standardom takim jak pyproject.toml, potężnym backendom budowania i bezpiecznej publikacji za pośrednictwem zaufanej publikacji. Korzystając z tego przewodnika, możesz tworzyć profesjonalne, utrzyjmalne pakiety Pythona, które skutecznie służą Twoim użytkownikom.
Kluczowe wnioski:
- Użyj pyproject.toml dla wszystkich nowych projektów
- Wybierz odpowiedni backend budowania dla Twoich potrzeb
- Zaimplementuj automatyczne testowanie i CI/CD
- Użyj zaufanej publikacji do bezpiecznej, beztokenowej dystrybucji
- Obserwuj semantyczne wersjonowanie i utrzymuj logi zmian
- Udostępniaj kompleksową dokumentację i przykłady
Ekosystem opakowań Pythona nadal się poprawia dzięki lepszym narzędziom, standardom i funkcjom bezpieczeństwa. Stosuj się do Python Enhancement Proposals (PEPs) i najlepszych praktyk społeczności, aby utrzymać swoje pakiety nowoczesne i utrzyjmalne.
Użyteczne linki
- Python Packaging User Guide
- PEP 518 - Specifying Build System Requirements
- PEP 621 - Storing project metadata in pyproject.toml
- PyPI Trusted Publishing Documentation
- Setuptools Documentation
- Poetry Documentation
- Hatch Documentation
- TestPyPI
- Python Packaging Authority GitHub
- Semantic Versioning
- Choose a License