Das Python-Ökosystem im Überblick (Stand: Juli 2020)

In diesem Beitrag geht es zur Abwechslung nicht um die Programmierung mit Python. Ich möchte das umfangreiche „Python-Ökosystem“ mit wenigen Worten vorstellen. Wer sich zum ersten Mal mit Python beschäftigt, wird mit vielen Namen konfrontiert, die alle etwas mit Python zu tun haben, aber doch etwas Eigenes sind. Da gibt es u.a. CPython, Jupyter, Anconda, IronPython, PyPy oder Django. Und dabei habe ich die „Hunderttausend“ Erweiterungen, die es für Python gibt, sowie die zahlreichen IDEs mit ihren teilweise ausgefallenen Namen gar nicht aufgezählt. Bis auf CPython sind alle Begriffe eine „Spielart“ von Python, die man installieren und mit der „man“ arbeiten kann.

Wer die Programmierung mit Python erlernen möchte, sollte Python für sein Betriebssystem in der aktuellsten Version von Python.org installieren und sich um die anderen Vertreter zunächst keine Gedanken machen. Als IDE (also als „Programmiereditor“) ist Idle sehr gut geeignet, das mit Python in der Regel installiert wird. Ansonsten empfehle ich Visual Studio Code als universellen Programmiereditor – hier muss die Python-Erweiterung von Microsoft aber einmalig nachinstalliert werden, was weniger als eine Minute in Anspruch nimmt. Alles kostenlos und für alle Plattformen verfügbar.

Der Reihe nach und alphabetisch.

Anaconda

Anaconda ist der Name einer Python-Distribution, die in den Datenwissenschaften eingesetzt wird. Nach eigener Aussage ist Anaconda die beliebteste Plattform für Datenanalye. Ihr Vorteil ist, dass alle für das Analysieren von Daten benötigten Packages von Anfang dabei sind (aktuell > 250). Auch wenn hinter Anaconda mit der Anaconda Inc. aus Austin/Texas in den USA ein kommerzieller Anbieter steht, ist Anaconda kostenlos.

https://de.wikipedia.org/wiki/Anaconda_(Python-Distribution)

CPython

CPython ist die Referenzimplementierung der Python-Foundation, in der alle Neuerungen implementiert werden. Wer eine eigene Python-Distribution herausgegeben möchte, sollte sich an CPython orientieren. Für den Anwender spielt CPython insofern eine Rolle, da die von der Python Foundation herausgegebene Python-Version auf diese Referenz-Implementierung basiert.

CPython ist das „Standard-Python“.

IronPython

IronPython ist ein bei Microsoft bereits im Jahr 2006 (!) gestartetes Open Source-Projekt. Es ist aktuell zu CPyton 2.7 kompatibel. Während Python eine eigene Laufzeitumgebung mitbringt, setzt IronPython auf dem .Net Framework, so dass die gesamte .Net-Klassenbibliothek zur Verfügung steht. Das ist vor allem für Entwickler, die ohnehin .Net verwenden, oder deren Programme nur unter WIndows ausführen sollen, attraktiv. Programmiert wird mit Microsoft Visual Studio, (nicht zu verwechseln mit Visual Studio Code), das in der Community Edition seit vielen Jahren kostenlos ist.

Nachdem der geistige Vater des Projekts, Jim Hugunin, Microsoft vor ein paar Jahren wieder verlassen hatte, schlief das Projekt offenbar etwas ein, wenngleich es laut Projektportal fortgeführt werden soll. Aktuell wird nur Python in der Version 2.7 unterstützt. Ob es eine Unterstützung für 3.x und eine Portierung auf .NET Core geben wird, so dass IronPython auch unter anderem Plattformen eingesetzt werden kann, hängt offenbar von der Frage ab, wer bereit ist an dem Projekt mitzuarbeiten.

https://de.wikipedia.org/wiki/IronPython

Jupyter

Die wichtigse Kleinigkeit vorweg. Es heißt „Jupyter“ und nicht „Jupiter“, da die Programmierumgebung zuerst nur für die drei Programmiersprachen Julia, Python und R umgesetzt wurde. Inzwischen werden viele weitere Sprachen als Kernel“ angeboten, so dass es sich um eine vielseitige Angelegenheit handelt. Ausgesprochen wird der Name aber wie der Planet bzw. es spielt auch keine ganz so große Rolle;)

Alles begann im Jahr 2014 mit Projekt IPython. IPython existiert aber weiter als Python-Implementierung und „Kernel“ für Jupyter und kann noch unabhängig von Jupyter installiert werden.

https://de.wikipedia.org/wiki/Project_Jupyter

Bei Jupyter arbeiten die User mit einem sog. Notebook, also einem Notizblock, in dem sie Befehle im Browser eingeben (auch dann, wenn Jupyter lokal installiert wurde). Wie bei der Python-Shell wird jeder Befehl sofort ausgeführt. Der große Vorteil ist, dass z.B. Listen, vor allem Datenstrukturen wie Matrizen, so ausgegeben werden, dass ihr Inhalt gut dargestellt wird. Auch Diagramme werden in die Ausgabe integriert. Weder muss Matplotlib installiert noch importiert werden. Das macht das Auswerten von Daten sehr komfortabel.

Da es so wichtig: Die Ausführung von Notebooks im Rahmen der Webplattform ist nur eine Option. Wurde Jupyter lokal installiert, steht grundsätzlich derselbe Komfort zur Verfügung. Jupyter ist damit ideal für das Lernen von Python geeignet und eine attraktive Alternative zur Python-Shell oder Idle.

Auch für ein lokal installiertes Jupyter lassen sich weitere Kernels hinzufügen, so dass auch in der Offline-Version andere Sprache als Python zur Auswahl stehen.

IPython

Wurde im letzten Abschnitt bereits erwähnt. War früher etwas Eigenes, ging dann in Juypter über, steht aber in der damaligen Version nach wie vor als etwas Eigenes zum Download zur Verfügung. In diesem Fall ist IPython eine komfortablere Python-Shell, die sich sehr gut zum Kennenlernen von Python eignet. Der Vorteil gegenüber Jupyter: Es muss deutlich weniger installiert werden, die Installation ist einfacher und am Ende arbeitet „man“ in einer vertrauten Shell, die aber mehr Komfort bietet und sich insgesamt „besser anfühlt“ als die etwas schlichte Python-Shell.

PyPy

PyPy ist ein Compiler für Python-Programme, der die Ausführung von Python-Programmen beschleunigen soll (ich habe damit aber noch nie gearbeitet). Inzwischen soll auch die Förderung des Projekts ausgelaufen sein, so dass die Fortführung des Projekts unsicher ist (dies ist aber lediglich meine persönliche Einschätzung und kein offizielles „Statement“).

https://de.wikipedia.org/wiki/PyPy

Umgang mit zweidimensionalen Feldern lernen – am Beispiel der Vigenére-Verschlüsselung

In diesem Beitrag möchte ich den Umgang mit zweidimensionalen Feldern in Python an einem sehr netten Beispiel veranschaulichen. Gleich vorweg, es gibt eigentlich keine mehrdimensionalen Felder in Python, sondern nur Listen, die als Elemente Listen enthalten. Und was bedeutet überhaupt zweidimensioal?

Ganz einfach, stellt Euch bitte kurz ein Brett vor, das aus horizontalen und vertikalen Reihen mit einer bestimmten und immer gleichen Anzahl an Feldern pro Reihe besteht. Bei einem Schachbrett gibt es bekanntlich acht Zeilen mit jeweils 8 Feldern. Also ein 8×8-Feld mit 64 Feldern. Bei einem Schiffe versenken-Spiel sind es 10 Reihen mit jeweils 10 Feldern. Also ein 10×10-Feld. Möchte man ein solches Brett mit seinen Feldern in einer Programmiersprache abbilden, benötigt man ein zweidimensionales Feld. Folglich gibt es auch zwei Indices. Für jede „Dimension“ ein Index.

Die allgemeine Schreibweise Feld[0,0] spricht das Feld in der linken, oberen Ecke an, die Schreibweise Feld[3,3] das Feld in der Mitte usw. Warum 0 und warum 3 und nicht 4? Ganz einfach, weil bei fast allen Programmiersprachen die Nummerierung bei 0 beginnt und nicht bei 1.

Wer sich im Internet ein wenig zum Thema „Python und Arrays“ umsieht findet schnell Beispiele, in denen Arrays verwendet werden. Kann Python daher doch Array?Nein und Ja. Nein, weil es Arrays offiziell nicht gibt. Ja, weil über Erweiterungen wie NumPy Arrays und Matrizen als eigene Datentypen hinzukommen. Im Folgenden geht es aber nur Listen, die wie Felder behandelt werden können.

Da das Beispielprogramm etwas umfangreicher ist und nicht jeder, der die Seite liest, sich bereits mit Feldern bei Python auskennt, zuerst ein Beispiel zur „Einstimmung“. Ich verwende aber mit Absicht keine Erweiterung wie NumPy, da es nur um die reine Python-Programmierung gehen soll.

Der erste Befehl legt eine leere Liste an:

f = []

Die Liste ist aber noch leer. Soll sie z.B. bereits zehn Nullen enthalten, ist List Comprehension praktisch, denn man spart sich eine for-Schleife mit Zuweisung:

f = [0 for i in range(0,10)]

Anschließend erhalten die ersten zwei oder drei Reihen ebenfalls eine Liste als Wert:

f[0] = [i for i in range(1,11)]
f[1] = [i for i in range(1,11)]
f[2] = [i for i in range(1,11)]

Natürlich hätte ich das Feld auch mit einem einzigen Befehl anlegen und befüllen können, aber so ist es etwas anschaulicher (dieser Befehl kommt in dem Beispielprogramm vor).

Jetzt wäre die Frage, wie ein Element, also eine Zahl, in der Listen-Liste angesprochen wird. Eigentlich sehr naheliegend durch folgende Schreibweise:

f[0][1]

Die bei anderen Programmiersprachen übliche Schreibweise f[0,1] geht bei Python nicht, da dies die Slicing-Schreibweise ist.

Jetzt zu dem eigentlichen Beispiel. Es veranschaulicht die Vigenére-Chiffre, die ich vor kurzem im Rahmen meines OMI-Studiums im Modul „Grundlagen der Informationssicherheit“ (GIS) kennengelernt habe.

Vigenére-Chiffre ermöglichen eine einfache“ Verschlüsselung“ Worten mit Hilfe eines Schlüssels, der wiederum nichts anderes als ein beliebiges Wort ist. Die Grundlage ist eine Tabelle mit z.B. 26 Spalten und 26 Zeilen. Warum 26? Damit alle Buchstaben des Alphabets in einer Zeile Platz haben. Die Tabelle ist so aufgebaut, dass jede Zeile die Buchstaben von A bis Z enthält, ab der zweiten Zeile aber immer um einen Buchstaben versetzt. Die erste Zeile beginnt mit A,B,C,D, die zweite mit B,C,D,E, die dritte mit C,D,E,F usw. Nach dem Z geht es in einer Zeile mit A wieder weiter.

Die Verschlüsselung besteht darin, dass das zu verschlüsselnde Wort Buchstabe für Buchstabe durchgegangen wird. Soll z.B. das Wort SOMMER verschlüsselt werden, gehen wir die Buchstaben S, O, M, M, E und R durch. Für jeden Buchstaben wird der Buchstabe mit jedem in Bezug auf die Position des Buchstabens korrespondierenden Buchstaben aus dem Schlüssel kombiniert. Heißt der Schlüssel z.B. GEHEIM, passt das S zum G, das O zum E, das M zum H usw. Der zweite Buchstabe legt die Zeile fest. Aus der Kombination Spalte und Zeile ergibt sich jeweils ein Buchstabe, der zum Chiffre hinzugefügt wird. Der Chiffre ist die verschlüsselte Form des Wortes.

Und was ist, wenn der Schlüssel kürzer ist als das zu verschlüsselnde Wort? Das ist natürlich kein Problem, wenn dann wird wieder der erste Buchstabe aus dem Schlüssel verwendet usw.

Wer das Ganze trotz meiner Bemühungen immer noch nicht verstanden hat, soll es bitte noch einmal bei Wikipedia nachlesen:

https://de.wikipedia.org/wiki/Vigen%C3%A8re-Chiffre

Dort wird alles natürlich viel komplizierter erklärt;)

Neben einer ausführlichen (und natürlich sehr guten) Erklärung findet ihr dort auch ein Beispiel für die von mir wortreich beschriebene Chiffre-Tabelle.

Doch nun zur Umsetzung in einem Python-Programm. Ich kann jedem nur empfehlen, die Aufgabe erst einmal selber zu lösen, da sie doch einiges an „Grundverständnis“ der Python-Programmierung abverlangt. Nicht, weil die Programmierung besonders kompliziert oder anspruchsvoll wäre, sondern weil es auf ein paar „Randbedingungen“ ankommt, die beim Programmieren immer das sprichwörtliche Salz in der Suppe sind.

Wenn man ein Wort erfolgreich verschlüsselt hat, möchte man es natürlich auch wieder lesbar machen. Das soll zunächst eine Übung sein, die jeder bitte alleine lösen soll, da die Lösung a) nicht schwer ist und ich b) niemanden das Erfolgserlebnis vorenthalten möchte. Probiert es einmal aus, es lohnt sich!

Das Beispiel findet ihr natürlich in meinem GitHub-Repo unter https://github.com/pemo11/pyhub. Am besten alle Beispiele (allzu viele sind es im Moment aber noch nicht) per git clone oder gleich in Visual Studio Code herunterladen (zur Not auch als Zip-Datei, wenn es mit den Git Tools für Windows wider Erwarten nicht funktionieren sollte).

# Vigenére Chiffre
# Umsetzung am 9.06.2020
# Autor: Peter Monadjemi
 
# Schritt 1: 26x26 Feld mit den jeweils pro Spalte um einen Buchstaben versetzen Buchstaben von A bis Z

# Thereotisch ließe sich das Fels auch gleich per List Comprehension passend füllen
vigFeld = [[0 for i in range(0,26)] for j in range(0,26)]

offset = 0

# Ergebnis stimmt, kann aber eventuell vereinfacht werden
for i in range(0,26):
    for j in range(0,26):
        c = j + offset + 65
        c = c - 26 if c > 90 else c
        vigFeld[i][j] = chr(c)
    offset += 1
 
for i in range(0,26):
    print(vigFeld[i])

# Das Wort "SEMESTER" soll mit dem Schlüssel SICHER verschüsselt werden
wort = "SEMESTER"
schluessel = "SICHER"
geheim = ""

k = 0
for c in wort:
    i = ord(c) - 65
    j = ord(schluessel[k]) - 65
    k = k + 1 if k < len(schluessel) - 1 else 0
    geheim += vigFeld[i][j]

# Stimmt - aus SEMESTER wird KMOLWKWZ
print(geheim)

# Wie muss eine Entschlüsselungsfunktion aussehen?