Kapitel 1. Erste Schritte in IPython und Jupyter

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Wenn ich Python-Code für Data Science schreibe, wechsle ich in der Regel zwischen drei Arbeitsweisen: Ich verwende die IPython-Shell, um kurze Befehlsfolgen auszuprobieren, das Jupyter Notebook für längere interaktive Analysen und um Inhalte mit anderen zu teilen, und interaktive Entwicklungsumgebungen (IDEs) wie Emacs oder VSCode, um wiederverwendbare Python-Pakete zu erstellen. Dieses Kapitel konzentriert sich auf die ersten beiden Modi: die IPython-Shell und das Jupyter Notebook. Die Verwendung einer IDE für die Softwareentwicklung ist ein wichtiges drittes Werkzeug im Repertoire eines Datenwissenschaftlers, aber darauf gehen wir hier nicht direkt ein.

Starten der IPython-Shell

Der Text in diesem Teil ist, wie der größte Teil dieses Buches, nicht dafür gedacht, passiv aufgenommen zu werden. Ich empfehle dir, beim Lesen mitzumachen und mit den Werkzeugen und der Syntax zu experimentieren, die wir behandeln: Das Muskelgedächtnis, das du dabei aufbaust, wird viel nützlicher sein, als wenn du nur darüber liest. Beginne damit, den IPython-Interpreter zu starten, indem du ipython auf der Kommandozeile eintippst. Wenn du eine Distribution wie Anaconda oder EPD installiert hast, gibt es vielleicht auch einen speziellen Launcher für dein System.

Sobald du dies getan hast, solltest du eine Eingabeaufforderung wie die folgende sehen:

Python 3.9.2 (v3.9.2:1a79785e3e, Feb 19 2021, 09:06:10)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.21.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

Damit bist du bereit, mitzumachen.

Starten des Jupyter Notebooks

Das Jupyter Notebook ist eine browserbasierte grafische Schnittstelle zur IPython-Shell und bietet darauf aufbauend eine Vielzahl von dynamischen Darstellungsmöglichkeiten. Neben der Ausführung von Python-/IPython-Anweisungen können in Notebooks auch formatierter Text, statische und dynamische Visualisierungen, mathematische Gleichungen, JavaScript-Widgets und vieles mehr eingefügt werden. Außerdem können diese Dokumente so gespeichert werden, dass andere Personen sie öffnen und den Code auf ihren eigenen Systemen ausführen können.

Obwohl du Jupyter-Notizbücher über dein Webbrowser-Fenster ansiehst und bearbeitest, müssen sie sich mit einem laufenden Python-Prozess verbinden, um Code ausführen zu können. Du kannst diesen Prozess (auch als "Kernel" bezeichnet) starten, indem du den folgenden Befehl in deiner System-Shell ausführst:

$ jupyter lab

Mit diesem Befehl wird ein lokaler Webserver gestartet, der für deinen Browser sichtbar ist. Er gibt sofort ein Log aus, das zeigt, was er tut. Dieses Log sieht etwa so aus:

$ jupyter lab
[ServerApp] Serving notebooks from local directory: /Users/jakevdp/ \
PythonDataScienceHandbook
[ServerApp] Jupyter Server 1.4.1 is running at:
[ServerApp] http://localhost:8888/lab?token=dd852649
[ServerApp] Use Control-C to stop this server and shut down all kernels
(twice to skip confirmation).

Nach der Eingabe des Befehls sollte sich dein Standardbrowser automatisch öffnen und zu der aufgeführten lokalen URL navigieren; die genaue Adresse hängt von deinem System ab. Wenn sich der Browser nicht automatisch öffnet, kannst du ein Fenster öffnen und diese Adresse manuell aufrufen( in diesem Beispielhttp://localhost:8888/lab/ ).

Hilfe und Dokumentation in IPython

Wenn du keinen anderen Abschnitt in diesem Kapitel liest, lies diesen: Für mich sind die hier besprochenen Werkzeuge die wichtigsten Beiträge von IPython zu meinem täglichen Arbeitsablauf.

Wenn eine technikbegeisterte Person gebeten wird, einem Freund, Familienmitglied oder Kollegen bei einem Computerproblem zu helfen, geht es meist weniger darum, die Antwort zu kennen, sondern darum, wie man eine unbekannte Antwort schnell findet. In der Datenwissenschaft ist das nicht anders: Durchsuchbare Webressourcen wie Online-Dokumentationen, Mailinglisten und Stack Overflow-Antworten enthalten eine Fülle von Informationen, auch (oder gerade?) zu Themen, die du schon einmal gesucht hast. Um in den Datenwissenschaften effektiv arbeiten zu können, geht es weniger darum, das Werkzeug oder den Befehl auswendig zu lernen, den du in jeder Situation verwenden solltest, sondern vielmehr darum, die Informationen, die du nicht kennst, effektiv zu finden, sei es über eine Internetsuchmaschine oder auf anderem Wege.

Eine der nützlichsten Funktionen von IPython/Jupyter ist es, die Kluft zwischen dem Benutzer und der Art von Dokumentation und Suche zu verkürzen, die ihm hilft, seine Arbeit effektiv zu erledigen. Zwar spielt die Websuche immer noch eine Rolle bei der Beantwortung komplizierter Fragen, aber eine erstaunliche Menge an Informationen kann allein durch IPython gefunden werden. Einige Beispiele für Fragen, die IPython mit ein paar Tastenanschlägen beantworten kann, sind:

  • Wie rufe ich diese Funktion auf? Welche Argumente und Optionen hat sie?

  • Wie sieht der Quellcode dieses Python-Objekts aus?

  • Was ist in dem Paket, das ich importiert habe?

  • Welche Attribute oder Methoden hat dieses Objekt?

Hier werden wir die Werkzeuge besprechen, die in der IPython-Shell und im Jupyter Notebook zur Verfügung stehen, um schnell auf diese Informationen zuzugreifen, nämlich das Zeichen ?, um die Dokumentation zu erkunden, die Zeichen ??, um den Quellcode zu erkunden, und die Tabulatortaste für die automatische Vervollständigung.

Zugriff auf die Dokumentation mit ?

Die Sprache Python und ihr Ökosystem für die Datenwissenschaft wurden mit Blick auf den Benutzer entwickelt, und ein wichtiger Teil davon ist der Zugang zur Dokumentation. Jedes Python-Objekt enthält einen Verweis auf eine Zeichenkette, den sogenannten docstring, der in den meisten Fällen eine kurze Zusammenfassung des Objekts und seiner Verwendung enthält. Python hat eine eingebaute Funktion help, die auf diese Informationen zugreifen und die Ergebnisse ausgeben kann. Um zum Beispiel die Dokumentation der eingebauten Funktion len anzuzeigen, kannst du Folgendes tun:

In [1]: help(len)
Help on built-in function len in module builtins:

len(obj, /)
    Return the number of items in a container.

Je nach Interpreter werden diese Informationen entweder als Inline-Text oder in einem separaten Pop-up-Fenster angezeigt.

Da die Suche nach Hilfe zu einem Objekt so häufig und nützlich ist, führen IPython und Jupyter das Zeichen ? als Abkürzung für den Zugriff auf diese Dokumentation und andere relevante Informationen ein:

In [2]: len?
Signature: len(obj, /)
Docstring: Return the number of items in a container.
Type:      builtin_function_or_method

Diese Notation funktioniert für so gut wie alles, auch für Objektmethoden:

In [3]: L = [1, 2, 3]
In [4]: L.insert?
Signature: L.insert(index, object, /)
Docstring: Insert object before index.
Type:      builtin_function_or_method

oder sogar Objekte selbst, mit der Dokumentation ihres Typs:

In [5]: L?
Type:        list
String form: [1, 2, 3]
Length:      3
Docstring:
Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.

Wichtig ist, dass dies auch für Funktionen oder andere Objekte funktioniert, die du selbst erstellst! Hier werden wir eine kleine Funktion mit einem Docstring definieren:

In [6]: def square(a):
  ....:     """Return the square of a."""
  ....:     return a ** 2
  ....:

Um einen Docstring für unsere Funktion zu erstellen, haben wir einfach ein String-Literal in die erste Zeile gesetzt. Da Docstrings in der Regel mehrzeilig sind, haben wir die Python-Schreibweise mit dreifachen Anführungszeichen für mehrzeilige Strings verwendet.

Jetzt benutzen wir die ?, um diesen Docstring zu finden:

In [7]: square?
Signature: square(a)
Docstring: Return the square of a.
File:      <ipython-input-6>
Type:      function

Dieser schnelle Zugriff auf die Dokumentation über Docstrings ist ein Grund, warum du dir angewöhnen solltest, deinem Code immer eine solche Inline-Dokumentation hinzuzufügen.

Zugriff auf den Quellcode mit ??

Weil die Sprache Python so leicht zu lesen ist, kann man in der Regel eine weitere Ebene des Einblicks gewinnen, indem man den Quellcode des Objekts liest, das einen interessiert. IPython und Jupyter bieten mit dem doppelten Fragezeichen (??) eine Abkürzung zum Quellcode:

In [8]: square??
Signature: square(a)
Source:
def square(a):
    """Return the square of a."""
    return a ** 2
File:      <ipython-input-6>
Type:      function

Bei einfachen Funktionen wie dieser kann das doppelte Fragezeichen einen schnellen Einblick in die Details unter der Haube geben.

Wenn du viel damit spielst, wirst du feststellen, dass das Suffix?? manchmal keinen Quellcode anzeigt: Das liegt in der Regel daran, dass das betreffende Objekt nicht in Python, sondern in C oder einer anderen kompilierten Erweiterungssprache implementiert ist. In diesem Fall liefert die Endung ?? die gleiche Ausgabe wie die Endung ?. Das ist vor allem bei vielen in Python eingebauten Objekten und Typen der Fall, z. B. bei der Funktion lenvon vorhin:

In [9]: len??
Signature: len(obj, /)
Docstring: Return the number of items in a container.
Type:      builtin_function_or_method

Mit ? und/oder ?? kannst du schnell und einfach herausfinden, was eine Python-Funktion oder ein Modul macht.

Module mit Tabulatorvervollständigung erforschen

Eine weitere nützliche Schnittstelle ist die Verwendung der Tabulatortaste für die automatische Vervollständigung und Erkundung des Inhalts von Objekten, Modulen und Namensräumen. In den folgenden Beispielen verwende ich <TAB>, um anzuzeigen, wann die Tabulatortaste gedrückt werden sollte.

Tabulatorische Vervollständigung des Objektinhalts

Jedes Python-Objekt hat verschiedene Attribute und Methoden, die mit ihm verbunden sind. Wie die bereits erwähnte Funktion help hat auch Python eine eingebaute Funktiondir, die eine Liste dieser Attribute zurückgibt, aber in der Praxis ist die Schnittstelle zur Tabulatorvervollständigung viel einfacher zu benutzen. Um eine Liste aller verfügbaren Attribute eines Objekts zu sehen, kannst du den Namen des Objekts gefolgt von einem Punkt (.) und der Tabulatortaste eingeben:

In [10]: L.<TAB>
            append() count    insert   reverse
            clear    extend   pop      sort
            copy     index    remove

Um die Liste einzugrenzen, kannst du den ersten Buchstaben oder mehrere Buchstaben des Namens eingeben und mit der Tabulatortaste die passenden Attribute und Methoden finden:

In [10]: L.c<TAB>
             clear() count()
             copy()

In [10]: L.co<TAB>
              copy()  count()

Wenn es nur eine einzige Option gibt, wird die Zeile durch Drücken der Tabulatortaste für dich vervollständigt. Zum Beispiel wird das Folgende sofort durchL.count ersetzt:

In [10]: L.cou<TAB>

Obwohl Python keine strikte Unterscheidung zwischen öffentlichen/externen Attributen und privaten/internen Attributen macht, wird in der Konvention ein vorangestellter Unterstrich verwendet, um letztere zu kennzeichnen. Aus Gründen der Übersichtlichkeit werden diese privaten Methoden und speziellen Methoden standardmäßig nicht in der Liste aufgeführt, aber es ist möglich, sie aufzulisten, indem du den Unterstrich explizit eingibst:

In [10]: L._<TAB>
           __add__             __delattr__     __eq__
           __class__           __delitem__     __format__()
           __class_getitem__() __dir__()       __ge__            >
           __contains__        __doc__         __getattribute__

Der Kürze halber habe ich nur die ersten paar Spalten der Ausgabe gezeigt. Die meisten davon sind Pythons spezielle Double-Underscore-Methoden (oft auch als "Dunder"-Methoden bezeichnet).

Tabulatorvervollständigung beim Importieren

Die Tabulatorvervollständigung ist auch beim Importieren von Objekten aus Paketen nützlich. Hier werden wir sie verwenden, um alle möglichen Importe im Paket itertoolszu finden, die mit co beginnen:

In [10]: from itertools import co<TAB>
         combinations()                  compress()
         combinations_with_replacement() count()

Ebenso kannst du mit der Tabulator-Vervollständigung sehen, welche Importe auf deinem System verfügbar sind (dies hängt davon ab, welche Skripte und Module von Drittanbietern für deine Python-Sitzung sichtbar sind):

In [10]: import <TAB>
            abc                 anyio
            activate_this       appdirs
            aifc                appnope        >
            antigravity         argon2

In [10]: import h<TAB>
            hashlib html
            heapq   http
            hmac

Jenseits der Tabulatorvervollständigung: Wildcard-Matching

Die Tabulatorvervollständigung ist nützlich, wenn du die ersten paar Zeichen des Namens des gesuchten Objekts oder Attributs kennst, aber wenig hilfreich, wenn du Zeichen in der Mitte oder am Ende des Namens finden möchtest. Für diesen Anwendungsfall bieten IPython und Jupyter die Möglichkeit, mit dem Zeichen * einen Platzhalter für Namen zu finden.

Damit können wir zum Beispiel jedes Objekt im Namensraum auflisten, dessen Name mit Warning endet:

In [10]: *Warning?
BytesWarning                  RuntimeWarning
DeprecationWarning            SyntaxWarning
FutureWarning                 UnicodeWarning
ImportWarning                 UserWarning
PendingDeprecationWarning     Warning
ResourceWarning

Beachte, dass das Zeichen * auf jede Zeichenkette passt, auch auf die leere Zeichenkette.

Nehmen wir an, wir suchen nach einer String-Methode, die das Wort find in ihrem Namen enthält. Wir können auf diese Weise danach suchen:

In [11]: str.*find*?
str.find
str.rfind

Ich finde, dass diese Art von flexibler Platzhaltersuche nützlich sein kann, um einen bestimmten Befehl zu finden, wenn ich ein neues Paket kennenlerne oder mich wieder mit einem vertrauten Paket vertraut mache .

Tastaturkürzel in der IPython-Shell

Wenn du auch nur ein bisschen Zeit am Computer verbringst, hast du wahrscheinlich schon eine Verwendung für Tastaturkürzel in deinem Arbeitsablauf gefunden. Am bekanntesten sind vielleicht Cmd-c und Cmd-v (oder Ctrl-c und Ctrl-v), die zum Kopieren und Einfügen in einer Vielzahl von Programmen und Systemen verwendet werden. Power-User neigen dazu, noch weiter zu gehen: Beliebte Texteditoren wie Emacs, Vim und andere bieten ihren Nutzern eine unglaubliche Bandbreite an Operationen durch komplizierte Kombinationen von Tastenkombinationen.

Die IPython-Shell geht nicht so weit, bietet aber eine Reihe von Tastenkombinationen für die schnelle Navigation bei der Eingabe von Befehlen. Während einige dieser Tastenkombinationen auch in den browserbasierten Notebooks funktionieren, geht es in diesem Abschnitt hauptsächlich um Tastenkombinationen in der IPython-Shell.

Wenn du dich erst einmal daran gewöhnt hast, können sie sehr nützlich sein, um bestimmte Befehle schnell auszuführen, ohne dass du deine Hände von der "Home"-Tastaturposition wegbewegen musst. Wenn du ein Emacs-Benutzer bist oder Erfahrung mit Linux-ähnlichen Shells hast, werden dir die folgenden Tastenkombinationen sehr vertraut sein. Ich werde diese Tastenkombinationen in einige Kategorien einteilen:Navigationskürzel, Texteingabekürzel, Befehlsverlaufskürzel und verschiedene Tastenkombinationen.

Navigationskurzbefehle

Während die Verwendung der linken und rechten Pfeiltasten, um sich in der Zeile vor und zurück zu bewegen, ziemlich offensichtlich ist, gibt es andere Optionen, bei denen du deine Hände nicht aus der Ausgangsposition der Tastatur bewegen musst:

Tastenanschlag Aktion

Strg-a

Cursor an den Anfang der Zeile bewegen

Strg-e

Cursor an das Ende der Zeile bewegen

Strg-b oder die linke Pfeiltaste

Cursor ein Zeichen zurückbewegen

Strg-f oder die rechte Pfeiltaste

Cursor ein Zeichen vorwärts bewegen

Tastenkombinationen für die Texteingabe

Jeder kennt zwar die Rücktaste, um das vorherige Zeichen zu löschen, aber der Griff zu dieser Taste erfordert oft ein wenig Fingergymnastik, und es wird immer nur ein einzelnes Zeichen gelöscht. In IPython gibt es mehrere Tastenkombinationen, mit denen du einen Teil des Textes, den du gerade tippst, löschen kannst; die nützlichsten davon sind die Befehle zum Löschen ganzer Textzeilen. Du weißt, dass dir diese Befehle in Fleisch und Blut übergegangen sind, wenn du eine Kombination aus Strg-b und Strg-d verwendest, anstatt zur Rücktaste zu greifen, um das vorherige Zeichen zu löschen!

Tastenanschlag Aktion

Rücktaste

Vorheriges Zeichen in der Zeile löschen

Ctrl-d

Nächstes Zeichen in der Zeile löschen

Strg-k

Text vom Cursor bis zum Ende der Zeile ausschneiden

Strg-u

Text vom Anfang der Zeile bis zum Cursor ausschneiden

Strg-y

Text, der zuvor ausgeschnitten wurde, einfügen

Ctrl-t

Transponiere (d.h. vertausche) die vorherigen zwei Zeichen

Befehlsverlaufs-Kurzbefehle

Die vielleicht einflussreichsten hier besprochenen Abkürzungen sind die, die IPython für die Navigation in der Befehlshistorie bereitstellt. Dieser Befehlsverlauf geht über deine aktuelle IPython-Sitzung hinaus: Dein gesamter Befehlsverlauf wird in einer SQLite-Datenbank in deinem IPython-Profilverzeichnis gespeichert.

Der einfachste Weg, um auf frühere Befehle zuzugreifen, ist die Verwendung der Pfeiltasten nach oben und unten, um durch den Verlauf zu gehen, aber es gibt auch andere Möglichkeiten:

Tastenanschlag Aktion

Strg-p (oder die Pfeiltaste nach oben)

Vorherigen Befehl in der Historie aufrufen

Strg-n (oder die Pfeiltaste nach unten)

Zugriff auf den nächsten Befehl in der Historie

Strg-r

Rückwärtssuche durch die Befehlshistorie

Die Option "Rückwärtssuche" kann besonders nützlich sein. Erinnere dich daran, dass wir früher eine Funktion namens square definiert haben. Lass uns von einer neuen IPython-Shell aus unsere Python-Geschichte rückwärts durchsuchen und diese Definition wiederfinden. Wenn du im IPython-Terminal Strg-r drückst, siehst du die folgende Eingabeaufforderung:

In [1]:
(reverse-i-search)`':

Wenn du an dieser Eingabeaufforderung anfängst, Zeichen einzugeben, füllt IPython automatisch den letzten Befehl aus, der mit diesen Zeichen übereinstimmt, falls vorhanden:

In [1]:
(reverse-i-search)`sqa': square??

Du kannst jederzeit weitere Zeichen hinzufügen, um die Suche zu verfeinern, oder erneut Strg-r drücken, um weiter nach einem anderen Befehl zu suchen, der der Abfrage entspricht. Wenn du schon früher mitgemacht hast, kannst du zweimal Strg-r drücken:

In [1]:
(reverse-i-search)`sqa': def square(a):
    """Return the square of a"""
    return a ** 2

Wenn du den gesuchten Befehl gefunden hast, drückst du die Eingabetaste und die Suche wird beendet. Du kannst dann den gefundenen Befehl verwenden und mit deiner Sitzung fortfahren:

In [1]: def square(a):
    """Return the square of a"""
    return a ** 2

In [2]: square(2)
Out[2]: 4

Beachte, dass du mit Strg-p/Strg-n oder den Pfeiltasten nach oben/unten deinen Verlauf auf ähnliche Weise durchsuchen kannst, allerdings nur nach Zeichen am Anfang der Zeile. Das heißt, wenn du def eintippst und dann Strg-p drückst, wird der letzte Befehl (falls vorhanden) in deinem Verlauf gesucht, der mit den Zeichen def beginnt.

Verschiedene Abkürzungen

Schließlich gibt es noch ein paar verschiedene Abkürzungen, die in keine der oben genannten Kategorien passen, aber trotzdem nützlich sind:

Tastenanschlag Aktion

Strg-l

Terminalbildschirm löschen

Ctrl-c

Aktuellen Python-Befehl unterbrechen

Ctrl-d

Beenden der IPython-Sitzung

Die Tastenkombination Strg-c kann besonders nützlich sein, wenn du versehentlich einen sehr lang laufenden Auftrag startest.

Auch wenn einige der hier besprochenen Abkürzungen zunächst etwas unverständlich erscheinen, werden sie mit etwas Übung schnell zur Selbstverständlichkeit. Wenn du erst einmal dieses Muskelgedächtnis entwickelt hast, wirst du dir vermutlich wünschen, dass sie auch in anderen Zusammenhängen verfügbar wären.

Get Python Data Science Handbook, 2. Auflage now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.