Bygg Python-paket: Guide från utveckling till PyPI

Mäster Python-paketering från kod till PyPI-distribution

Sidinnehåll

Python-paketering har utvecklats betydligt, med moderna verktyg och standarder som gör det enklare än någonsin att distribuera din kod.

Den här guiden leder dig genom att bygga professionella Python-paket och publicera dem på PyPI. Om du är nybörjare i Python eller behöver en snabb referens, kolla in vår Python Cheatsheet för att komma igång med grunderna i Python.

Python Paket

Varför paketera din Python-kod?

Att paketera ditt Python-projekt erbjuder flera fördelar:

  • Återanvändbarhet: Dela kod mellan flera projekt utan att kopiera och klistra in
  • Distribution: Låt andra installera din kod med ett enkelt pip install
  • Beroendehantering: Klart specificera och hantera beroenden
  • Versionering: Följ upp utgåvor och bibehålla bakåtkompatibilitet
  • Professionella standarder: Följ Python-communityns bästa praxis
  • Dokumentation: Strukturen uppmuntrar till ordentlig dokumentation och testning

Modern Python-paketstruktur

Ett välorganiserat paket följer denna struktur:

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 föredras nu framför flat layout eftersom det:

  • Förhindrar oavsiktliga importer av icke-installerad kod under utveckling
  • Gör testning mer tillförlitlig genom att tvinga installation
  • Skiljer tydligt källkod från andra projektfiler

När du organiserar ditt pakets interna struktur, överväg att tillämpa principer för ren arkitektur för att göra din kod mer underhållbar och testbar. Vår guide om Python Design Patterns for Clean Architecture täcker SOLID-principer, beroendeinjektion och lagerarkitektur som fungerar utmärkt med Python-paket.

Filen pyproject.toml: Modern konfiguration

pyproject.toml (PEP 518, 621) är den moderna standarden för Python-projektkonfiguration, som ersätter den äldre setup.py:

[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "0.1.0"
description = "Ett fantastiskt Python-paket"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
    {name = "Ditt Namn", email = "du@example.com"}
]
keywords = ["exempel", "tutorial", "paket"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: 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/dittanvändarnamn/mypackage"
Documentation = "https://mypackage.readthedocs.io"
Repository = "https://github.com/dittanvändarnamn/mypackage"
Issues = "https://github.com/dittanvändarnamn/mypackage/issues"

[project.scripts]
mypackage-cli = "mypackage.cli:main"

[tool.setuptools.packages.find]
where = ["src"]

Viktiga konfigurationer

  1. build-system: Anger byggverktyg (setuptools, hatchling, poetry-core, flit-core)
  2. project: Grundläggande metadata och beroenden
  3. project.optional-dependencies: Extra beroenden för funktioner (dev, docs, testning)
  4. project.scripts: Kommandoradsentrypunkter
  5. tool.*: Verktygsspecifik konfiguration (black, pytest, mypy, etc.)

Val av byggverktyg

Setuptools (Standardval)

Det mest använda och kompatibla alternativet:

[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"

Fördelar: Universell kompatibilitet, omfattande funktioner, stort ekosystem Nackdelar: Mer omfattande konfiguration, långsammare än nya alternativ

Hatchling (Modern & Snabb)

Lättvikts och prestandastarkt modernt verktyg:

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Fördelar: Snabba byggningar, enkel konfiguration, bra standarder Nackdelar: Färre plugins än setuptools

Poetry (Allt-i-ett)

Komplett beroende- och miljöhantering:

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "mypackage"
version = "0.1.0"
description = "Ett fantastiskt Python-paket"
authors = ["Ditt Namn <du@example.com>"]

[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"

Fördelar: Beroendeupplösning, låsfiler, integrerad arbetsflöde Nackdelar: Annorlunda arbetsflöde, större verktygsyta

Flit (Minimalistisk)

Enkelt verktyg för enkla paket:

[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"

Fördelar: Extremt enkelt, minimal konfiguration Nackdelar: Begränsade funktioner för komplexa paket

Bygg ditt paket

Installera byggverktyg

# Installera det moderna byggverktyget
pip install build

# Eller för Poetry
pip install poetry

# Eller för Hatchling
pip install hatch

Bygg distributionsfiler

Använd paketet build (fungerar med alla verktyg):

# Rensa tidigare byggningar
rm -rf dist/ build/ *.egg-info

# Bygg källfördelning och wheel
python -m build

# Detta skapar:
# dist/mypackage-0.1.0.tar.gz    (källfördelning)
# dist/mypackage-0.1.0-py3-none-any.whl  (wheel)

Använd Poetry:

poetry build

Använd Hatch:

hatch build

Förstå distributionsformat

Källfördelning (sdist) - .tar.gz

  • Innehåller källkod och bygginstruktioner
  • Användarens pip bygger den under installation
  • Inkluderar tester, dokumentation och andra utvecklingsfiler

Wheel - .whl

  • Förbyggd binärfördelning
  • Snabb installation (inget byggsteg)
  • Plattformspecifik eller ren Python
  • Rekommenderat format för distribution

Publicera på PyPI

Metod 1: Manuell uppdatering med Twine (Traditionell)

# Installera twine
pip install twine

# Kontrollera paketet innan uppdatering
twine check dist/*

# Ladda upp till TestPyPI först (rekommenderas)
twine upload --repository testpypi dist/*

# Testa installation från TestPyPI
pip install --index-url https://test.pypi.org/simple/ mypackage

# Ladda upp till produktions-PyPI
twine upload dist/*

Konfigurera autentisering i ~/.pypirc:

[distutils]
index-servers =
    pypi
    testpypi

[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmc...

[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgENdGVzdC5weXBpLm9yZw...

Metod 2: Betrodd publicering (Rekommenderas för CI/CD)

Betrodd publicering använder OpenID Connect (OIDC) för att autentisera från CI/CD-plattformar utan att lagra token.

Inställning i PyPI:

  1. Gå till dina PyPI-projektinställningar
  2. Navigera till avsnittet “Publishing”
  3. Lägg till en ny “pending publisher”
  4. Konfigurera:
    • Ägare: Ditt GitHub-användarnamn/organisation
    • Repository: Repositorynamn
    • Arbetsflöde: publish.yml
    • Miljö: release (valfritt men rekommenderas)

GitHub Actions Arbetsflöde (.github/workflows/publish.yml):

name: Publicera till PyPI

on:
  release:
    types: [published]

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Konfigurera Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Installera byggberoenden
        run: |
          python -m pip install --upgrade pip
          pip install build          

      - name: Bygg paket
        run: python -m build

      - name: Lagra distributionspaket
        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: Hämta distributionspaket
        uses: actions/download-artifact@v3
        with:
          name: python-package-distributions
          path: dist/

      - name: Publicera till PyPI
        uses: pypa/gh-action-pypi-publish@release/v1

Fördelar:

  • Inga API-token att hantera eller säkra
  • Automatisk autentisering via OIDC
  • Förbättrad säkerhet genom miljöskyddsregler
  • Revisionsspårning av alla publiceringar

Bäst praxis

1. Versionshantering

Använd semantisk versionering (SemVer): MAJOR.MINOR.PATCH

# Installera versionshöjningsverktyg
pip install bump2version

# Höj version
bump2version patch  # 0.1.0 -> 0.1.1
bump2version minor  # 0.1.1 -> 0.2.0
bump2version major  # 0.2.0 -> 1.0.0

Konfigurera i .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. Inkludera väsentliga filer

README.md: Klar projektbeskrivning, installationsanvisningar, användningsexempel LICENSE: Välj lämplig licens (MIT, Apache 2.0, GPL, etc.) CHANGELOG.md: Dokumentera ändringar mellan versioner .gitignore: Exkludera byggprodukter, cache, virtuella miljöer

3. Komplett testning

# Installera testberoenden
pip install pytest pytest-cov

# Kör tester med täckningsrapportering
pytest --cov=mypackage tests/

# Generera täckningsrapport
pytest --cov=mypackage --cov-report=html tests/

Konfigurera i pyproject.toml:

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "--strict-markers --cov=mypackage"

4. Kvalitetsverktyg för kod

# Formatering
black src/ tests/

# Lintning
flake8 src/ tests/

# Typkontroll
mypy src/

# Importsortering
isort src/ tests/

Integrera i 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. Dokumentation

Använd Sphinx för dokumentation:

# Installera Sphinx
pip install sphinx sphinx-rtd-theme

# Initiera dokumentation
cd docs
sphinx-quickstart

# Bygg dokumentation
make html

Eller använd MkDocs för enklare Markdown-baserad dokumentation:

pip install mkdocs mkdocs-material
mkdocs new .
mkdocs serve

6. Kontinuerlig integration

Att testa dina Python-paket över olika plattformar och miljöer är avgörande för tillförlitlighet. För insikter om Python-prestanda i olika distributionsscenarier, se vår jämförelse av AWS Lambda-prestanda: JavaScript vs Python vs Golang, som utforskar hur Python presterar i serverlösa miljöer.

Komplett CI/CD-flöde (.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: Konfigurera Python
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}

      - name: Installera beroenden
        run: |
          python -m pip install --upgrade pip
          pip install -e ".[dev]"          

      - name: Kör tester
        run: pytest --cov=mypackage --cov-report=xml

      - name: Ladda upp täckning
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage.xml

  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Konfigurera Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Installera beroenden
        run: |
          pip install black flake8 mypy          

      - name: Black-formateringskontroll
        run: black --check src/ tests/

      - name: Flake8
        run: flake8 src/ tests/

      - name: MyPy
        run: mypy src/

Vanliga fallgropar och lösningar

Problem 1: Importeringsfel efter installation

Problem: Paketet installerat men importering misslyckas

Lösning: Se till att du har rätt paketstruktur med __init__.py-filer och korrekt pyproject.toml-konfiguration:

[tool.setuptools.packages.find]
where = ["src"]
include = ["mypackage*"]

Problem 2: Saknade beroenden

Problem: Paketet installerat men misslyckas vid körning på grund av saknade beroenden

Lösning: Ange alla körningsberoenden i pyproject.toml:

[project]
dependencies = [
    "requests>=2.28.0",
    "click>=8.1.0",
]

Problem 3: Versionskonflikter

Problem: Paketet fungerar i utveckling men misslyckas i produktion

Lösning: Använd virtuella miljöer och ange minimiversioner:

# Skapa isolerad miljö
python -m venv .venv
source .venv/bin/activate  # På Windows: .venv\Scripts\activate

# Installera i redigeringsläge för utveckling
pip install -e ".[dev]"

Problem 4: Stort paketstorlek

Problem: Paketet tar för lång tid att ladda ner/installera

Lösning: Exkludera onödiga filer med 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: Plattformspecifika problem

Problem: Paketet fungerar på ett operativsystem men misslyckas på ett annat

Lösning: Testa på flera plattformar med hjälp av CI/CD-matrisbyggnader (se CI-exempel ovan)

Publiceringschecklista

Innan du publicerar ditt paket till PyPI, verifiera:

  • Alla tester går igenom över Python-versioner
  • Koden är formaterad och lintad
  • README.md är komplett med exempel
  • LICENSE-fil är inkluderad
  • Versionsnummer är uppdaterat
  • CHANGELOG.md är uppdaterad
  • Beroenden är korrekt angivna
  • Paketet byggs utan fel (python -m build)
  • Paketet testat på TestPyPI
  • Dokumentationen är uppdaterad
  • Git-repositoryn är märkt med version
  • GitHub-release är skapad (för betrodd publicering)

Avancerade ämnen

Entry Points och CLI-verktyg

Skapa kommandoradsgränssnitt:

[project.scripts]
mypackage = "mypackage.cli:main"

Implementering i src/mypackage/cli.py:

import click

@click.command()
@click.option('--name', default='World', help='Namn att hälsa')
def main(name):
    """Exempel på enkelt CLI-verktyg"""
    click.echo(f'Hello, {name}!')

if __name__ == '__main__':
    main()

För ett verkligt exempel på att skapa Python-paket som interagerar med externa API:er, se vår guide om Integrering av Ollama med Python, som demonstrerar byggandet av Python-klienter med både REST-API och officiella biblioteksintegreringar.

Plugin-system

Aktivera plugin-upptäckt:

[project.entry-points."mypackage.plugins"]
plugin_a = "mypackage_plugin_a:PluginA"

C-extensioner

För prestandakritisk kod:

[tool.setuptools.ext-modules]
name = "mypackage._speedups"
sources = ["src/mypackage/_speedups.c"]

Namnrymdspaket

För distribuerade paket under en gemensam namnrymd:

[tool.setuptools.packages.find]
where = ["src"]
include = ["company.*"]

[tool.setuptools.package-data]
"company.mypackage" = ["py.typed"]

Användbara verktyg och resurser

Paketutvecklingsverktyg

  • cookiecutter: Projektmallar för Python-paket
  • tox: Testautomatisering över Python-versioner
  • nox: Flexibel testautomatisering (tox-alternativ)
  • pre-commit: Git-hook-ramverk för kodkvalitet
  • commitizen: Standardisera commit-meddelanden och versionshantering

Dokumentationsplattformar

  • Read the Docs: Gratis dokumentationsvärd
  • GitHub Pages: Värd för MkDocs eller Sphinx-dokumentation
  • pdoc: Enkel API-dokumentationsgenerator

Paketregister

  • PyPI: Det officiella Python Package Index (pypi.org)
  • TestPyPI: Testmiljö (test.pypi.org)
  • Anaconda.org: Conda-paketdistribution
  • GitHub Packages: Privat paketvärd

Övervakning och analys

  • PyPI Stats: Nedladdningsstatistik för paket
  • Libraries.io: Beroendeövervakning och varningar
  • Snyk: Säkerhetsriskanalys
  • Dependabot: Automatiserade beroendeuppdateringar

Slutsats

Modern Python-paketering har utvecklats för att vara utvecklarvänlig med standarder som pyproject.toml, kraftfulla byggsystem och säker publicering via Trusted Publishing. Genom att följa denna guide kan du skapa professionella, underhållbara Python-paket som effektivt tjänar dina användare.

Viktiga slutsatser:

  1. Använd pyproject.toml för alla nya projekt
  2. Välj rätt byggsystem för dina behov
  3. Implementera automatiserad testning och CI/CD
  4. Använd Trusted Publishing för säker, tokenfri distribution
  5. Följ semantisk versionering och underhåll changelogs
  6. Ge omfattande dokumentation och exempel

Python-paketeringsekosystemet fortsätter att förbättras med bättre verktyg, standarder och säkerhetsfunktioner. Håll dig uppdaterad med Python Enhancement Proposals (PEPs) och community-bäst praxis för att hålla dina paket moderna och underhållbara.

Användbara länkar

Andra användbara artiklar på denna sida