Die Struktur eines Python-Projekts

    Ein Python-Projekt mag am Anfang nur aus ein oder zwei Dateien bestehen. Über eine Projektstruktur muss man sich in diesem Fall keine Gedanken machen. Anders sieht es aber aus, wenn das Programm wächst. Neben den eigentlichen Python-Dateien könnte irgendwann auch noch eine Dokumentation dazukommen. Und in der Regel sollen die Tests in separaten Dateien und einem eigens dafür vorgesehenen Verzeichnis gespeichert werden. Es stellt sich dann zwangsläufig die Frage nach einer sinnvollen Struktur.

    Diese Frage ist nicht einfach zu beantworten. Denn im Internet sowie der einschlägigen Fachliteratur finden sich dazu unterschiedliche Vorschläge. Mit anderen Worten: Es gibt nicht die Projektstruktur. So sind die nachfolgenden Ausführungen ebenfalls nur als Vorschlag zu verstehen.

    Eine einfache Projektstruktur

    Eine typische Struktur für ein Projekt mit dem Namen „my_project“ könnte folgendermaßen aussehen:

    .
    ├── README.md
    ├── docs
    ├── src
    │   ├── __init__.py
    │   └── main.py
    ├── pyproject.toml
    ├── pytest.ini
    ├── requirements-dev.txt
    ├── requirements.txt
    ├── setup.cfg
    ├── setup.py
    └── tests
        └── __init__.py

    Im Stammverzeichnis des Projekts „my_project“ befinden sich drei Unterordner:

    • src: Mit „src“ ist das Quellcode-Verzeichnis gemeint, also jenes Verzeichnis, in dem die Dateien mit dem Python-Code gespeichert werden. Dieses Verzeichnis enthält in diesem Beispiel zwei Dateien:
      • Bei dem Verzeichnis my_project handelt sich um ein Paket (Package), weswegen dieser Ordner eine Datei namens __init__.py enthält. Diese Datei ist (heutzutage) in der Regel leer. Sie wird aufgerufen, wenn ein Modul dieses Pakets importiert wird.
      • Die Datei main.py enthält den Python-Code. Sie ist der Einstiegspunkt in dieses Programm.
    • docs: In diesem Verzeichnis befinden sich alle notwendigen Dateien für die Dokumentation (z.B. für den Dokumentations-Generator Sphinx).
    • tests: Hier befinden sich alle Dateien, die Tests enthalten. Auch dieses Verzeichnis hat eine Datei mit dem Namen __init__.py. Sofern als Test-Framework pytest verwendet wird, kann im Projektordner noch optional eine Konfigurationsdatei für pytest dazukommen: pytest.ini.

    Ein Projekt lässt sich auch dergestalt organisieren, dass im Verzeichnis src ein Unterverzeichnis erstellt wird, das den gleichen Namen hat wie das Projekt. In diesem Verzeichnis befinden sich dann die Dateien __init__.py, main.py sowie gegebenenfalls weitere Module. Außerdem ist tests ein Unterverzeichnis von src, während docs im Stammverzeichnis bleibt.

    my_project/
    ├── src/
       ├── my_project/
          ├── __init__.py
          ├── main.py
          ├── module1.py
          └── ...
       └── tests/
    ├── docs/
    ├── pyproject.toml
    ├── pytest.ini
    └── README.md

    requirements.txt

    Die für ein Projekt erforderlichen externen Bibliotheken, zum Beispiel numpy oder matplotlib könnten in der Datei requirements.txt stehen. Eine Installation wäre dann mit pip bzw. pip3 möglich:

    pip3 install -r requirements.txt # Linux, macOS
    pip install -r requirements.txt  # Windows

    Manche Entwickler lagern jene Pakete, die nicht unmittelbar für die Ausführung des Projekts erforderlich sind, in eine Datei namens requirements-dev.txt aus (z.B. könnte man pytest in dieser Datei aufführen). Dies ist jedoch optional. Diese Pakte können, falls erforderlich, ebenfalls mit pip bzw. pip3 installiert werden:

    pip3 install -r requirements-dev.txt # Linux, macOS
    pip install -r requirements-dev.txt  # Windows

    Heutzutage ist es aber üblich, etwaige Bibliotheken in die Datei pyproject.toml zu schreiben. Die Dateien requirements.txt und requirements-dev.txt sind dann nicht erforderlich.

    [project]
    name = "my_project"
    version = "0.1.0"
    dependencies = [
        "requests >= 2.28.0",
        "pandas >= 3.0.0",
        "numpy",
                
    [project.optional-dependencies]
    dev = [
        "pytest",
        "black",
    ]

    Auf die Datei pyproject.toml wird im nächsten Abschnitt genauer eingegangen.

    Konfigurationsdateien

    Bei den Dateien pyproject.toml, setup.py und setup.cfg handelt es sich um Konfigurationsdateien, die Informationen über das Projekt, wie seine Abhängigkeiten, Metadaten (z.B. Name, Version, Beschreibung), Build-Anweisungen und mehr enthalten.

    Heutzutage wird nur noch die Datei pyproject.toml benötigt. Sie enthält alle Informationen zum Projekt.

    Bei den Dateien setup.py und setup.cfg handelt es sich um ältere Konfigurationsdateien. Bei Verwendung von pyproject.toml werden sie grundsätzlich nicht mehr benötigt. Da sie noch häufig in älteren Python-Projekten enthalten sind, werde ich dennoch der Vollständigkeit halber auf sie eingehen.

    setup.py und setup.cfg

    Früher existierte nur eine Datei mit dem Namen setup.py. Falls nur diese Datei (und nicht auch noch setup.cfg) verwendet wurde, enthielt sie die Metadaten zum Projekt. Für unser Beispielprojekt könnte sie folgenden Inhalt haben:

    from setuptools import setup, find_packages
    
    VERSION = '0.1.0'
    
    setup(
        name='my_project',
        version=VERSION,
        license='MIT',
        description='Just an example.',
        author='My Name',
        author_email='my_name@xyz.com',
        url='https://github.com/<user>/<project>',
        python_requires='>=3.8'
    
        package_dir={"": "src"},
        packages=find_packages(where="src"),
    
        entry_points={
            'console_scripts': [
                'my_project = main:main',,
            ],
        },
    )

    Die Datei setup.py konnte sehr komplex und unübersichtlich werden. Deswegen wurde die Konfigurationsdatei setup.cfg eingeführt, die die erforderlichen Metadaten enthält. Häufig traten die Konfigurationsdateien als Duo auf: Die Datei setup.py enthielt die Build-Anweisungen, die Datei setup.cfg die Metadaten. Diese Kombination war lange Zeit der Standard. Und diese Arbeitsteilung war früher auch erforderlich, da ältere Versionen von pip und setuptools nicht wussten, dass sie die Datei setup.cfg aufrufen mussten.

    Bei der Kombination von setup.py und setup.cfg reduzierte sich der Inhalt von setup.py auf zwei Zeilen:

    import setuptools
    
    # Sucht automatisch setup.cfg im selben Ordner:
    setuptools.setup()

    Und setup.cfg hätte folgendermaßen aussehen können:

    [metadata]
    name = my_project
    author = My Name
    author-email = my_name@xyz.com
    license = MIT
    long_description = file: README.md
    url = 'https://github.com/<user>/<project>'
    requires-python = >= 3.8
    
    [options]
    package_dir =
        = src
    packages = find:
    install_requires =
    	requests >= 2.45.0
    
    [options.packages.find]
    where = src
    
    [options.entry_points]
    console_scripts =
    	my_project = src.main:main

    Die Datei pyproject.toml

    Von der Vergangenheit kommen wir nun in die Gegenwart, d.h. wir kommen nun zur Datei pyproject.toml. Sie reicht heutzutage als Konfigurationsdatei aus. Diese Datei ermöglicht durch die Angabe eines Build-Systems das Erstellen eines Installations-Pakets. Im folgenden Beispiel wird als Build-System setuptools verwendet:

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

    Anstelle von setuptools, können auch Hatchling, Flip, PDM oder uv-build verwendet werden. Falls ihr wissen möchtet, welche Informationen zum jeweiligen Build-System in der Datei pyproject.toml enthalten sein müssen, hilft euch der Python Packaging User Guide weiter.

    Mit der Angabe des Build-Systems ist es übrigens möglich, ein Python-Programm auf der Plattform pypi.org zu veröffentlichen (so dass eine Installation mit dem Befehl pip durchgeführt werden kann).

    Hinweis: Es ist denkbar, dass ihr auf Projekte stoßt, die sowohl die Datei pyproject.toml als auch die Datei setup.cfg haben. Die Datei pyproject.toml enthält in diesem Fall nur die Angaben zum Build-System, während die Datei setup.cfg die übrigen Informationen enthält.

    Nach der Angabe des Build-Systems folgen die weiteren Informationen zum Projekt. Die Datei pyproject.toml könnte wie folgt aussehen:

    [build-system]
    requires = ["setuptools", "wheel"]
    build-backend = "setuptools.build_meta"
    
    [project]
    name = "my_project"
    version = "1.0.0"
    description = "Project description"
    readme = "README.md"
    requires-python = ">=3.12"
    license = { text = "MIT" }
    authors = [
        { name = "Your Name", email = "name@xyz.com" }
    ]
    urls = {"Homepage" = "https://github.com/username/project_name"}
    
    classifiers = [
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: 3.14",
        "Programming Language :: Python :: Implementation :: CPython"
    ]
    
    dependencies = [
        "requests >= 2.28.0",
        "pandas >= 3.0.0",
        "numpy",
    ]
    
    [project.optional-dependencies]
    dev = [
        "pytest",
        "black",
    ]
    
    [project.scripts]
    my_project = "src.main:main"

    Hinweis: In den gezeigten Beispielen zu den Dateien setup.py, setup.cfg und pyproject.toml wurde davon ausgegangen, dass sich die Datei main.py direkt im Verzeichnis src befindet.

    Ergänzende Hinweise

    Die Datei main.py stellt den Einstiegspunkt des Programms dar. Die Bezeichnung kann frei gewählt werden, aber häufig heißt diese Datei main.py oder cli.py (wenn es sich um ein Konsolenprogramm handelt).

    Es ist eine gute Idee, zu jedem Projekt eine README.md hinzuzufügen. Spätestens wenn ein Projekt veröffentlicht wird, ist so eine Datei erforderlich und bietet Dritten eine Orientierung. Ergänzend findet sich in Projekten (bei Github, GitLab, etc.) häufig auch eine CONTRIBUTING.md, die anderen Entwicklern Hinweise zur Teilnahme am Projekt bietet.

    Werft bei Python-Projekten auf Github einen Blick auf die Dateien setup.py, setup.cfg und pyproject.toml. So erhaltet Ihr einen Eindruck davon, welche Metadaten andere Entwickler hinzugefügt haben.

    Auf Github findet Ihr ein Shellskript, das ihr dafür verwenden könnt, automatisch ein Projekt-Grundgerüst zu erstellen. Dieses Skript erhebt keinen Anspruch auf Vollständigkeit. Es mag aber ein guter Ausgangspunkt für ein eigenes Skript sein.

    Im Internet finden sich weitere gute Beispiele zur Projektstruktur, zum Beispiel im Artikel „Ultimate Setup for Your Next Python Project“, der auch Beispiele zu den Konfigurationsdateien enthält.

    Eine Übersicht zu weiteren Artikeln zur Programmiersprache Python findest Du auf dieser Seite.

    Zuletzt aktualisiert am 28. Januar 2026