#!/usr/bin/env python # coding: utf-8 # # Eigenständige Pythonprogramme # # Außerhalb des IPython Notebooks wird direkt in Textdateien mit der Endung "`.py`" programmiert. # Diese Dateien verhalten sich wie große Zellen, die vom Python Interpreter vollständig ausgewertet werden. # 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. # # Im folgenden das wichtigste, wie man eine einzelne Python Datei erzeugt: # # 1. Man nehme eine normale Textdatei, der Editor sollte problemlos [UTF-8](http://en.wikipedia.org/wiki/UTF-8) beherrschen. # 1. Üblicherweise beginnt das Programm mit einer kleinen Definition, dass es tatsächlich ein Python Programm ist. Die erste Zeile ist daher: # ``` # #!/usr/bin/env python # ``` # 1. Die UTF-8 Kodierung wird in der zweiten Zeile üblicherweise nochmals explizit mittels # ``` # # -*- coding: UTF-8 -*- # ``` # angegeben. # 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. # 1. Dann kommt das eigentliche Programm, welches oft mit `import`-Statements beginnt und dann Funktionen und Klassen definiert. # 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: # ``` # if __name__ == "__main__": # ... # ... # ``` # # Jetzt ein konkretes Beispiel zur besseren Veranschaulichung: # In[1]: get_ipython().run_cell_magic('writefile', 'res/program1.py', '#!/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\nimport math\n\ndef 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\nif __name__ == "__main__":\n z = 21\n print("Program started, z = %f" % z)\n result = calculate(z)\n print("Result = %f" % result)\n') # Die vorherige Zelle speichert beim Ausführen durch "`%%writefile`" den Inhalt in der angegebenen Datei ("`res/program1.py`") ab. # # Nun führen wir das Programm mit dem Python-Interpreter aus (Das `!` schickt den angegebenen Befehl direkt an die Kommandozeile) # In[2]: get_ipython().system('python res/program1.py') # ## Argumente # # Programme haben üblicherweise Eingaben, unter anderem in der Form von Kommandozeilenargumenten. # Das sind einzelne Zeichenketten, die dem Programmaufruf in der Kommandozeile nachgestellt werden. # Diese Strings sind dann in `sys.args` vom Programm aus abrufbar. # # Beispiel: # In[3]: get_ipython().run_cell_magic('writefile', 'res/program2.py', '#!/usr/bin/env python\nif __name__ == "__main__":\n import sys\n for idx, arg in enumerate(sys.argv):\n print("Argument %2d: %s" % (idx, arg))\n') # In[4]: get_ipython().system('python res/program2.py xx argument2 "with a space"') # Es ist neben dieser einfachen Art der Parameterübergabe auch eine komplexere Art möglich. # Oft will man nur ausgewählte Parameter übergeben. # Die geschieht mit einem speziellen Syntax (vorangestellte "`-`" und "`--`"), # welcher zwischen boolschen Flags und Variablen unterscheidet, # durch das [Argparse](https://docs.python.org/3/howto/argparse.html) modul. # # Beispiel: # # $ python program3.py 21 --negate --y=21 # In[5]: get_ipython().run_cell_magic('writefile', 'res/program3.py', '#!/usr/bin/env python\n\ndef 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\nif __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)\n') # In[6]: get_ipython().system('python res/program3.py 21') # In[7]: get_ipython().system('python res/program3.py 21 --negate') # In[8]: get_ipython().system('python res/program3.py 10 --y=0') # Und es gibt außerdem eine Hilfe, und eine implizite Kontrolle ob die Argumente korrekt übergeben wurden: # In[9]: get_ipython().system('python res/program3.py --y=0') # In[10]: get_ipython().system('python res/program3.py 70 -ngate') # In[11]: get_ipython().system('python res/program3.py --help') # In[11]: