123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- {
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "pycharm": {
- "name": "#%% md\n"
- },
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "# Software Entwicklung \n",
- "\n",
- "## Kapitel 9: IO\n",
- "\n",
- "Unter *IO* (Input/Output) versteht man alle Mechanismen,\n",
- "die mit dem Ausleiten von Daten aus einem Programm\n",
- "bzw. dem Einlesen von Daten in ein Programm zusammenhängen."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "pycharm": {
- "name": "#%% md\n"
- },
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "### 9.1 Zeichenkodierung\n",
- "\n",
- "Möchte ein Programm Daten senden (z.B. in eine Datei\n",
- "oder über eine Netzwerkverbindung) oder diese empfangen,\n",
- "werden letztendlich Bytes übertragen. Handelt es sich bei den\n",
- "Daten um Text - also lesbare Zeichen - so muss durch eine\n",
- "Zeichenkodierung (engl. *encoding*) festgelegt werden,\n",
- "wie dieser Text auf Bytes abgebildet wird.\n",
- "\n",
- "Ein sehr übliches Kodierungsschema ist *UTF-8*. Darin werden\n",
- "die Zahlen 0 bis 127 analog zum alten ASCII-Standard\n",
- "insbesondere für grundlegende lateinische Zeichen in\n",
- "Groß- und Kleinschrift verwendet. Alle übrigen Zeichen wie\n",
- "z.B. deutsche Umlaute, chinesische Schriftzeichen,\n",
- "Emojis etc. werden durch größere Zahlen ggf. mit mehreren\n",
- "Bytes codiert. Die Zuordnung der Zahlen zu den Zeichen\n",
- "ist durch den [*Unicode*-Standard](http://www.unicode.org/)\n",
- "festgelegt."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Möchte man eine Python-Zeichenkette in eine Unicode-Bytefolge\n",
- "übertragen, so kann dafür die Methode <code>encode</code> der Klasse\n",
- "*str* (String) verwendet werden."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "text = \"Nürnberg ist schön\"\n",
- "print(f\"Länge {len(text)}\")\n",
- "utf8 = text.encode(\"utf-8\")\n",
- "print(utf8)\n",
- "print(f\"Länge {len(utf8)}\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "Das vorangestellte <code>b</code> signalisiert, dass es sich\n",
- "hier um eine Bytefolge handelt."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "print(type(utf8))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Eine solche Bytefolge kann auch wieder in einen\n",
- "Textstring verwandelt werden. Dazu besitzt die\n",
- "Klasse *bytes* die Methode <code>decode</code>."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "decoded_text = utf8.decode(\"utf-8\")\n",
- "print(decoded_text)\n",
- "print(f\"Länge {len(decoded_text)}\")\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "### 9.2 Dateien\n",
- "\n",
- "Unter *Textdateien* verstehen wir Dateien, die\n",
- "mit einem Texteditor erzeugt und bearbeitet werden können.\n",
- "Der Inhalt sind lesbare Zeichen, die meist\n",
- "in Zeilen organisiert sind. Um sie auf einem\n",
- "Speichermedium abzulegen, müssen die Zeichen\n",
- "in Bytes konvertiert bzw. beim Lesen\n",
- "rückübertragen werden.\n",
- "\n",
- "*Binärdateien* sind Dateien, für die keine Kodierung\n",
- "stattfinden soll (z.B. Bilder).\n",
- "\n",
- "Python besitzt bereits im Standard Funktionen, Klassen und Methoden,\n",
- "die das Lesen und Schreiben von Dateien sowie das Übertragen\n",
- "von Text in Bytes (und zurück) unterstützen."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Einstiegspunkt ist die Built-In-Funktion <code>open</code>, die ein\n",
- "Dateiobjekt zurückliefert. Die Parameter von <code>open</code> sind\n",
- "der *Dateiname* (ggf. inkl. Pfad) und der *Bearbeitungsmodus*\n",
- "sowie weitere, weniger gebräuchliche optionale Parameter.\n",
- "\n",
- "\n",
- "| *Bearbeitungsmodus* | *Bedeutung* |\n",
- "|:--------------------:|----------------------------------------------------|\n",
- "| 'r' | Die Datei wird gelesen (muss bereits existieren) |\n",
- "| 'w' | Die Datei wird geschrieben (vorhandene Datei wird überschrieben) |\n",
- "| 'a' | Die Datei wird geschrieben (neuer Inhalt wird angehängt) |\n",
- "| 'r+' | Die Datei wird gelesen und geschrieben |\n",
- "\n",
- "Standardmäßig finden die Lese- und Schreiboperationen mit der Standard-Kodierung des verwendeten Betriebssystems statt. Soll die Kodierung unterbleiben, muss an den Bearbeitungsmodus ein <code>'b'</code>\n",
- "(für binär) angehängt werden."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- },
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "f = open(\"091a Textdatei\", \"r\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Das auf diese Weise erhaltene Dateiobjekt kann für (je nach\n",
- "Bearbeitungsmodus) für das Lesen und Schreiben benutzt werden.\n",
- "Die Methode <code>read</code> ohne Angabe eines Parameter\n",
- "liest den gesamten Inhalt der Datei ein\n",
- "(Vorsicht: nur bei kleinen Dateien ratsam, da speicherintensiv)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "content = f.read()\n",
- "print(content)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Jedes geöffnete Dateiobjekt muss auch wieder geschlossen werden,\n",
- "da andernfalls Betriebssystemressourcen dauerhaft belegt bleiben."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "print(f.closed)\n",
- "f.close()\n",
- "print(f.closed)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Sollte eine Textdatei in einer anderen Kodierung als die Standard-Kodierung vorliegen, kann die gewünschte Kodierung mittels des Parameters <code>encoding</code> angegeben werden. Mit <code>encoding=None</code> wird wieder die Standard-Kodierung gewählt, was dem Standardwert und damit dem Weglassen des Parameters entspricht. Im folgenden Beispiel wird eine Textdatei geladen, die im UTF-8-Format vorliegt. Die Standard-Kodierung auf Windows weicht allerdings davon ab, wie man an den Umlauten erkennen kann."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "f = open(\"utf8_text\", \"r\", encoding=None)\n",
- "content = f.read()\n",
- "print(content)\n",
- "f.close()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "### 9.3 Kontextmanager\n",
- "\n",
- "Die strenge Verpflichtung, jede Datei auch zu schließen, ist\n",
- "gelegentlich nicht einfach zu erfüllen. Falls z.B. eine\n",
- "Exception auftritt und die Abarbeitungsreihenfolge\n",
- "abgebrochen wird, ist trotzdem *close* aufzurufen."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- },
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "try:\n",
- " f = open(\"091a Textdatei\", \"r\")\n",
- " z = 1 / 0\n",
- " # f.close() würde nicht erreicht!\n",
- "except:\n",
- " print(\"Fehler!\")\n",
- "finally:\n",
- " f.close()\n",
- "print(f.closed)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Python bietet für dieses Problem den *Kontextmanager* an. Er\n",
- "initialisiert einen *Kontext* für ein Objekt, führt einen\n",
- "Codeblock in diesem Kontext aus und räumt beim Verlassen\n",
- "des *Kontext* belegte Ressourcen auf.\n",
- "\n",
- "Das Schlüsselwort für den Beginn eines *Kontext* ist <code>with</code>."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "with open(\"091a Textdatei\", \"r\") as f:\n",
- " print(f.read())\n",
- " print(f.closed)\n",
- "\n",
- "print(f.closed)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "slide"
- }
- },
- "source": [
- "Wie ist das realisiert? Tatsächlich nutzt der\n",
- "*Kontextmanager* die beiden *dunder*-Methoden\n",
- "<code>\\_\\_entry\\_\\_</code> und <code>\\_\\_exit\\_\\_</code>.\n",
- "Die Methode <code>\\_\\_entry\\_\\_</code> wird beim Betreten des\n",
- "Kontext aufgerufen, die Methode <code>\\_\\_exit\\_\\_</code> beim\n",
- "Verlassen oder beim Auftreten einer nicht behandelten Exception.\n",
- "\n",
- "Beim Datei-Objekt von Python wird in der\n",
- "<code>\\_\\_exit\\_\\_</code>-Methode sichergestellt, dass die\n",
- "Datei geschlossen wird.\n",
- "\n",
- "Durch Überschreiben der Methoden können auch eigene Klassen\n",
- "sinnvoll mit einem *Kontextmanager* zusammenarbeiten.\n",
- "\n",
- "\n"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Slideshow",
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.9"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
- }
|