{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Eigenständige Pythonprogramme\n", "\n", "Außerhalb des IPython Notebooks wird direkt in Textdateien mit der Endung \"`.py`\" programmiert.\n", "Diese Dateien verhalten sich wie große Zellen, die vom Python Interpreter vollständig ausgewertet werden.\n", "Darauf aufbauend, kann das einzelne Programm andere Python Dateien laden (mittels `import`) bzw. eine Sammlung von Python Dateien kann ein vollständiges Python Modul bilden.\n", "\n", "Im folgenden das wichtigste, wie man eine einzelne Python Datei erzeugt:\n", "\n", "1. Man nehme eine normale Textdatei, der Editor sollte problemlos [UTF-8](http://en.wikipedia.org/wiki/UTF-8) beherrschen.\n", "1. Üblicherweise beginnt das Programm mit einer kleinen Definition, dass es tatsächlich ein Python Programm ist. Die erste Zeile ist daher:\n", " ```\n", " #!/usr/bin/env python\n", " ```\n", "1. Die UTF-8 Kodierung wird in der zweiten Zeile üblicherweise nochmals explizit mittels\n", " ```\n", " # -*- coding: UTF-8 -*-\n", " ```\n", " angegeben. \n", "1. Es folgt (ebenfalls optional) ein längerer Kommentar zwichen `\"\"\"` oder mit vorangestellten `#`, die erklären was das Programm ist, was es machen sollte, wer es Programmiert hat, unter welcher Lizenz es steht, etc.\n", "1. Dann kommt das eigentliche Programm, welches oft mit `import`-Statements beginnt und dann Funktionen und Klassen definiert.\n", "1. Den Schluss bildet ein Block Code, welcher nur dann ausgeführt wird, wenn das Programm tatsächlich als eigenständiges Programm und nicht als Bibliothek aufgerufen wird. Dies wird so angegeben:\n", " ```\n", " if __name__ == \"__main__\":\n", " ...\n", " ...\n", " ```\n", " \n", "Jetzt ein konkretes Beispiel zur besseren Veranschaulichung:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting res/program1.py\n" ] } ], "source": [ "%%writefile res/program1.py\n", "#!/usr/bin/env python\n", "# -*- coding: utf8 -*-\n", "# This is an example, which contains all the main parts for a proper standalone program\n", "# Copyright: Harald Schilly , 2014\n", "# License: Apache 2.0\n", "import math\n", "\n", "def calculate(x):\n", " \"\"\"\n", " The important calculation\n", " \"\"\"\n", " if x < 0:\n", " y = - x\n", " else:\n", " y = math.sqrt(x)\n", " return x + y\n", "\n", "if __name__ == \"__main__\":\n", " z = 21\n", " print(\"Program started, z = %f\" % z)\n", " result = calculate(z)\n", " print(\"Result = %f\" % result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die vorherige Zelle speichert beim Ausführen durch \"`%%writefile`\" den Inhalt in der angegebenen Datei (\"`res/program1.py`\") ab.\n", "\n", "Nun führen wir das Programm mit dem Python-Interpreter aus (Das `!` schickt den angegebenen Befehl direkt an die Kommandozeile)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Failed to import the site module\r\n", "Traceback (most recent call last):\r\n", " File \"/projects/anaconda3/lib/python3.5/site.py\", line 72, in \r\n", " import os\r\n", " File \"/projects/anaconda3/lib/python3.5/os.py\", line 666, in \r\n", " from _collections_abc import MutableMapping\r\n", " File \"/projects/anaconda3/lib/python3.5/_collections_abc.py\", line 56\r\n", " async def _coro(): pass\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python res/program1.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Argumente\n", "\n", "Programme haben üblicherweise Eingaben, unter anderem in der Form von Kommandozeilenargumenten.\n", "Das sind einzelne Zeichenketten, die dem Programmaufruf in der Kommandozeile nachgestellt werden.\n", "Diese Strings sind dann in `sys.args` vom Programm aus abrufbar.\n", "\n", "Beispiel:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting res/program2.py\n" ] } ], "source": [ "%%writefile res/program2.py\n", "#!/usr/bin/env python\n", "if __name__ == \"__main__\":\n", " import sys\n", " for idx, arg in enumerate(sys.argv):\n", " print(\"Argument %2d: %s\" % (idx, arg))" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Failed to import the site module\r\n", "Traceback (most recent call last):\r\n", " File \"/projects/anaconda3/lib/python3.5/site.py\", line 72, in \r\n", " import os\r\n", " File \"/projects/anaconda3/lib/python3.5/os.py\", line 666, in \r\n", " from _collections_abc import MutableMapping\r\n", " File \"/projects/anaconda3/lib/python3.5/_collections_abc.py\", line 56\r\n", " async def _coro(): pass\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python3 res/program2.py xx argument2 \"with a space\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Es ist neben dieser einfachen Art der Parameterübergabe auch eine komplexere Art möglich.\n", "Oft will man nur ausgewählte Parameter übergeben.\n", "Die geschieht mit einem speziellen Syntax (vorangestellte \"`-`\" und \"`--`\"),\n", "welcher zwischen boolschen Flags und Variablen unterscheidet,\n", "durch das [Argparse](https://docs.python.org/3/howto/argparse.html) modul.\n", "\n", "Beispiel:\n", " \n", " $ python program3.py 21 --negate --y=21" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting res/program3.py\n" ] } ], "source": [ "%%writefile res/program3.py\n", "#!/usr/bin/env python\n", "\n", "def parse_args():\n", " import argparse\n", " parser = argparse.ArgumentParser()\n", " # mandatory x value, no prefix\n", " parser.add_argument(\"x\", type=int, help=\"The x value\")\n", " # optional y value\n", " parser.add_argument(\"--y\", type=int, help=\"The optional y value\", default=42)\n", " # \"negate\"-flag\n", " parser.add_argument(\"--negate\", action=\"store_true\", help=\"Should x be negated?\")\n", " return parser.parse_args()\n", "\n", "if __name__ == \"__main__\":\n", " args = parse_args()\n", " print(\"Arguments: %s\" % args)\n", " \n", " x = args.x\n", " if args.negate:\n", " x = -x\n", " result = x + args.y\n", " print(\"Result: %f\" % result)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " File \"/projects/anaconda3/lib/python3.5/site.py\", line 176\r\n", " file=sys.stderr)\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python res/program3.py 21" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " File \"/projects/anaconda3/lib/python3.5/site.py\", line 176\r\n", " file=sys.stderr)\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python res/program3.py 21 --negate" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " File \"/projects/anaconda3/lib/python3.5/site.py\", line 176\r\n", " file=sys.stderr)\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python res/program3.py 10 --y=0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Und es gibt außerdem eine Hilfe, und eine implizite Kontrolle ob die Argumente korrekt übergeben wurden:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " File \"/projects/anaconda3/lib/python3.5/site.py\", line 176\r\n", " file=sys.stderr)\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python res/program3.py --y=0" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " File \"/projects/anaconda3/lib/python3.5/site.py\", line 176\r\n", " file=sys.stderr)\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python res/program3.py 70 -ngate" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " File \"/projects/anaconda3/lib/python3.5/site.py\", line 176\r\n", " file=sys.stderr)\r\n", " ^\r\n", "SyntaxError: invalid syntax\r\n" ] } ], "source": [ "!python res/program3.py --help" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Anaconda (Python 3)", "language": "python", "name": "anaconda3" }, "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }