Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/tox-dev/pyproject-fmt
rev: v2.11.1
rev: v2.16.2
hooks:
- id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.24.1
rev: v0.25
hooks:
- id: validate-pyproject
- repo: https://github.com/sphinx-contrib/sphinx-lint
Expand All @@ -37,14 +37,14 @@ repos:
- id: sphinx-lint
types: [rst]
- repo: https://github.com/pycqa/isort
rev: 7.0.0
rev: 8.0.1
hooks:
- id: isort
additional_dependencies: ["toml"]
entry: isort --profile=black
name: isort (python)
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 25.12.0
rev: 26.1.0
hooks:
- id: black
- repo: https://github.com/tonybaloney/perflint
Expand Down
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Python4DataScience
==================

.. _badges:
.. _badges

Status
------
Expand All @@ -29,7 +29,7 @@ Status
:alt: Mastodon
:target: https://mastodon.social/@Python4DataScience

.. _first-steps:
.. _first-steps

Überblick
---------
Expand Down Expand Up @@ -125,7 +125,7 @@ Installation
Das PDF findet ihr anschließend in ``docs/_build/latex/jupytertutorial.pdf``.


.. _follow-us:
.. _follow-us

Folge uns
---------
Expand Down
2 changes: 0 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import os
import re


# Set canonical URL for the sitemap
html_baseurl = "https://python4data.science/de/latest/"

Expand All @@ -33,7 +32,6 @@
import os
import re


project = "Python für Data Science"
author = "Veit Schiele"
copyright = f"2019–2025, {author}"
Expand Down
2 changes: 0 additions & 2 deletions docs/data-processing/apis/fastapi/example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ Erstellt die Datei :file:`main.py` mit diesem Inhalt:

from fastapi import FastAPI


app = FastAPI()


Expand Down Expand Up @@ -81,7 +80,6 @@ zu erhalten:

from fastapi import FastAPI


app = FastAPI()


Expand Down
2 changes: 1 addition & 1 deletion docs/data-processing/apis/grpc/accounts_pb2.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: accounts.proto
"""Generated protocol buffer code."""

from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database


# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()
Expand Down
1 change: 1 addition & 0 deletions docs/data-processing/apis/grpc/accounts_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""

import accounts_pb2 as accounts__pb2
import grpc

Expand Down
6 changes: 2 additions & 4 deletions docs/data-processing/postgresql/db-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,10 @@ Cursor
.. code-block:: python

cursor = conn.cursor()
cursor.execute(
"""
cursor.execute("""
SELECT column1, column2
FROM tableA
"""
)
""")
for column1, column2 in cursor.fetchall():
print(column1, column2)

Expand Down
2 changes: 0 additions & 2 deletions docs/data-processing/postgresql/sqlalchemy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ Datenbankverbindung

from sqlalchemy import create_engine


engine = create_engine("postgresql:///example", echo=True)

Datenmodell
Expand All @@ -56,7 +55,6 @@ Datenmodell
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship


Base = declarative_base()


Expand Down
20 changes: 20 additions & 0 deletions docs/data-processing/serialisation-formats/json/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,26 @@ JSON-Tools
.. image:: https://raster.shields.io/github/license/stefankoegl/python-json-patch
:alt: Lizenz

`jsonata-python <https://github.com/rayokota/jsonata-python>`_
`JSONata <https://docs.jsonata.org/overview.html>`_ ist eine
leichtgewichtige Abfrage- und Transformationssprache für JSON-Daten,
inspiriert von XPath.

.. image:: https://raster.shields.io/github/stars/rayokota/jsonata-python
:alt: Stars
:target: https://github.com/rayokota/jsonata-python

.. image:: https://raster.shields.io/github/contributors/rayokota/jsonata-python
:alt: Contributors
:target: https://github.com/rayokota/jsonata-python/graphs/contributors

.. image:: https://raster.shields.io/github/commit-activity/y/rayokota/jsonata-python
:alt: Commit activity
:target: https://github.com/rayokota/jsonata-python/graphs/commit-activity

.. image:: https://raster.shields.io/github/license/rayokota/jsonata-python
:alt: Lizenz

.. _`standard`: https://www.json.org/json-en.html
.. _`JSON_Checker`: http://www.json.org/JSON_checker/
.. _`JSON Schema Proposal`: https://json-schema.org
Expand Down
1 change: 0 additions & 1 deletion docs/data-processing/serialisation-formats/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ lines_between_types = 1
multi_line_output = 3
not_skip = "__init__.py"
use_parentheses = true

known_first_party = "jupyter-tutorial"
known_third_party = [ "mpi4py", "numpy", "requests" ]
1 change: 0 additions & 1 deletion docs/data-processing/serialisation-formats/toml/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ Beispiel

import toml


config = toml.load("pyproject.toml")

.. seealso::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ lines_between_types = 1
multi_line_output = 3
not_skip = "__init__.py"
use_parentheses = true

known_first_party = [ "MY_FIRST_MODULE", "MY_SECOND_MODULE" ]
known_third_party = [ "mpi4py", "numpy", "requests" ]
32 changes: 24 additions & 8 deletions docs/performance/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ zu kümmern.
<http://www.literateprogramming.com/>`_, in Computer Programming as an
Art (1974)

.. seealso::
* `Speed up your data science and scientific computing code
<https://pythonspeed.com/datascience/>`_

k-Means-Beispiel
----------------

Expand Down Expand Up @@ -51,7 +55,6 @@ Beispieldaten können wir uns erstellen mit:

from sklearn.datasets import make_blobs


points, labels_true = make_blobs(
n_samples=1000, centers=3, random_state=0, cluster_std=0.60
)
Expand All @@ -67,18 +70,25 @@ Performance-Messungen

Wenn ihr erst einmal mit eurem Code gearbeitet habt, kann es nützlich sein, die
Effizienz genauer zu untersuchen. Hierfür kann :abbr:`z. B. (zum Beispiel)`
`cProfile <https://docs.python.org/3.14/library/profile.html#module-cProfile>`_,
:doc:`ipython-profiler` oder :doc:`scalene` genutzt werden.
:doc:`cProfile <tracing>`, :doc:`ipython-profiler`, :doc:`scalene`, :doc:`tprof`
oder :doc:`memray` genutzt werden. Bisher führe ich meist die folgenden Schritte
aus:

#. Ich profilierte das gesamte Programm mit :doc:`cProfile <tracing>` oder
`py-spy <https://github.com/benfred/py-spy>`_, um langsame Funktionen zu
finden.
#. Anschließend optimiertee ich eine langsame Funktion.
#. Schließlich erstellte ich ein neues Profil und filterte das Ergebnis meiner
optimierten Version heraus um die Ergebnisse vergleichen zu können.

.. versionadded:: Python3.15
Mit :pep:`799` wird ein spezielles Profiling-Modul zur Verfügung stehen, das
die in Python integrierten Profiling-Tools unter einem einheitlichen
Namespace organisiert. Dieses Modul enthält:

:mod:`profiling.tracing`
deterministische Funktionsaufrufverfolgung, die aus `cProfile
<https://docs.python.org/3.14/library/profile.html#module-cProfile>`_
verschoben wurde.
deterministische Funktionsaufrufverfolgung, die aus :doc:`cProfile
<tracing>` verschoben wurde.
:mod:`profiling.sampling`
der neue statistische Sampling-Profiler :doc:`tachyon`.

Expand All @@ -96,8 +106,11 @@ Effizienz genauer zu untersuchen. Hierfür kann :abbr:`z. B. (zum Beispiel)`
:titlesonly:
:maxdepth: 0

tracing
ipython-profiler.ipynb
scalene.ipynb
tprof
memray
tachyon

Suche nach bestehenden Implementierungen
Expand All @@ -114,7 +127,6 @@ k-Means-Algorithmus gibt es sogar gleich zwei Implementierungen:

from sklearn.cluster import KMeans


KMeans(10).fit_predict(points)

* `dask_ml.cluster.KMeans
Expand All @@ -124,7 +136,6 @@ k-Means-Algorithmus gibt es sogar gleich zwei Implementierungen:

from dask_ml.cluster import KMeans


KMeans(10).fit(points).predict(points)

Gegen diese bestehenden Lösungen könnte bestenfalls sprechen, dass sie einen
Expand Down Expand Up @@ -293,6 +304,11 @@ wissenschaftlichen Python- und NumPy-Code in schnellen Maschinencode
Numba benötigt allerdings `LLVM <https://de.wikipedia.org/wiki/LLVM>`_ und
einige Python-Konstrukte werden nicht unterstützt.

.. seealso::
* `Speeding up NumPy with parallelism
<https://pythonspeed.com/articles/numpy-parallelism/> by Itamar
Turner-Trauring`_

Aufgabenplaner
--------------

Expand Down
Binary file added docs/performance/memray-flamegraph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
97 changes: 97 additions & 0 deletions docs/performance/memray.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
.. SPDX-FileCopyrightText: 2026 Veit Schiele
..
.. SPDX-License-Identifier: BSD-3-Clause

Memray
======

Die Speichernutzung ist in Python-Projekten nur schwer zu kontrollieren, da die
Sprache nicht explizit deutlich macht, wo Speicher zugewiesen wird, Modulimporte
können den Verbrauch erheblich steigern, und es ist nur allzu leicht, eine
Datenstruktur zu erstellen, die versehentlich unbegrenzt wächst.
Data-Science-Projekte sind besonders anfällig für hohen Speicherverbrauch, da
sie meist viele große Abhängigkeiten wie :doc:`/workspace/numpy/index`
importieren, selbst wenn diese nur an wenigen Stellen verwendet werden.

`Memray <https://bloomberg.github.io/memray/>`_ hilft euch, die Speichernutzung
eures Programms zu verstehen, wobei nachverfolgt wird, wo während der
Programmausführung Speicher zugewiesen und freigegeben wird. Diese Daten können
dann auf verschiedene Weise dargestellt werden, :abbr:`u. a. (uter anderem)`
werden in `Flame Graphs <https://www.brendangregg.com/flamegraphs.html>`_ die
`Stacktraces <https://de.wikipedia.org/wiki/Stacktrace>`_ in einem Diagramm
zusammengefasst, wobei die Balkenbreite die Größe der Speicherzuweisung
darstellt.

Mit ``memray run`` kann jeder Python-Befehl profiliert werden. Für die meisten
Projekte empfiehlt sich, zunächst mit ``check`` die Funktion zu profilieren, die
euer Projekt lädt. Damit wird der Mindestaufwand überprüft, der zum Starten
eurer Anwendung erforderlich ist, :abbr:`z.B. (zum Beispiel)`:

.. code-block:: console

$ uv run memray run src/items/__init__.py check
Writing profile results into src/items/memray-__init__.py.72633.bin
[memray] Successfully generated profile results.

You can now generate reports from the stored allocation records.
Some example commands to generate reports:

/Users/veit/items/.venv/bin/python3 -m memray flamegraph src/items/memray-__init__.py.72633.bin

Der Befehl gibt die Meldung ``Successfully generated profile results.`` aus und
erstellt eine Datei :samp:`{PROCESS-ID}.bin`-Datei. Den *Flame Graph* können wir
dann erstellen mit:

.. code-block:: console

$ uv run python -m memray flamegraph src/items/memray-__init__.py.72633.bin
Wrote src/items/memray-flamegraph-__init__.py.72633.html

.. tip::
In vielen Konsolen könnt ihr die beiden Befehle zusammenfassen mit ``&&``:

.. code-block:: console

$ uv run memray run src/items/__init__.py check && uv run python -m memray flamegraph src/items/memray-__init__.py.72633.bin

Das Ergebnis ist folgende HTML-Datei:

.. figure:: memray-flamegraph.png
:alt: memray flamegraph report

memray flamegraph report

Der Kopfbereich der Seite enthält einige Steuerelemente, :abbr: `u.a. (unter anderem)` zu

*Memory Graph*
Anzeige des Speicherplatzes eines Prozesses im Arbeitsspeicher (`Resident
set size <https://en.wikipedia.org/wiki/Resident_set_size>`_) und des
`dynamischen Speichers
<https://de.wikipedia.org/wiki/Dynamischer_Speicher>`_ (Heap Memory) über
die Zeit
*Stats*
Speicherstatistiken, in diesem Fall

.. code-block:: text

Command line: /Users/veit/items/.venv/bin/memray run src/items/api.py check
Start time: Sun Feb 08 2026 12:12:27 GMT+0100 (Central European Standard Time)
End time: Sun Feb 08 2026 12:12:27 GMT+0100 (Central European Standard Time)
Duration: 0:00:00.068000
Total number of allocations: 11142
Total number of frames seen: 0
Peak memory usage: 4.6 MB
Python allocator: pymalloc

Darunter befindet sich der *Flame-Graph* als Eiszapfendiagramm mit den
Speicherzuweisungen über die Zeit, wobei der letzte Aufruf ganz unten steht. Die
Grafik zeigt die zu einem bestimmten Zeitpunkt ausgeführte Codezeile an wobei
die Breite proportional zur zugewiesenen Speichermenge ist; bewegt ihr die Maus
darüber, seht ihr weitere Details wie Dateiname, Zeilennummer, zugewiesener
Speicher und Anzahl der Zuweisungen.

.. tip::
Mit :ref:`python-basics:pytest_memray` gibt es auch ein Plugin für
:doc:`python-basics:test/pytest/index`, mit dem ihr überprüfen könnt, ob
von euch festgelegte Obergrenzen für den Speicherverbrauch und Speicherlecks
eingehalten werden.
Loading
Loading