{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# IPython-Magie\n", "\n", "IPython ermöglicht nicht nur Python interaktiv zu verwenden, sondern erweitert auch die Python-Syntax um sog. *Magic Commands*, die mit dem Präfix `%` versehen werden. Sie wurden entwickelt, um häufig auftretende Probleme bei der Datenanalyse schnell und einfach lösen zu können. Dabei wird zwischen zwei verschiedenen Arten von *Magic Commands* unterschieden:\n", "\n", "* *line magics*, die durch einen einzelnen `%`-Präfix gekennzeichnet sind und auf einer einzelnen Eingabezeile ausgeführt werden\n", "* *cell magics*, denen ein doppeltes Symbol `%%` vorangestellt wird und die innerhalb einer Notebook-Zelle ausgeführt werden." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Externen Code ausführen: `%run`\n", "\n", "Wenn ihr anfangt, umfangreicheren Code zu entwickeln, arbeitet ihr vermutlich sowohl in IPython für interaktive Erkundungen als auch in einem Texteditor zum Speichern von Code, den ihr wiederverwenden möchtet. Mit der `%run`-Magie könnt ihr diesen Code direkt in eurer IPython-Sitzung ausführen.\n", "\n", "Stellt euch vor, ihr hättet eine `myscript.py`-Datei mit folgendem Inhalt erstellt:\n", "\n", "``` Python\n", "def square(x):\n", " return x ** 2\n", "\n", "for N in range(1, 4):\n", " print(N, \"squared is\", square(N))\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 squared is 1\n", "2 squared is 4\n", "3 squared is 9\n" ] } ], "source": [ "%run myscript.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Beachtet, dass nach dem Ausführen dieses Skripts alle darin definierten Funktionen für die Verwendung in eurer IPython-Sitzung verfügbar sind:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "16" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "square(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Es gibt verschiedene Möglichkeiten, die Ausführung eures Codes zu verbessern. Wie üblich, könnt ihr euch die Dokumentation in IPython anzeigen lassen mit `%run?`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Timing-Code ausführen: `%timeit`\n", "\n", "Ein weiteres Beispiel für eine Magic-Funktion ist `%timeit`, die automatisch die Ausführungszeit der darauf folgenden einzeiligen Python-Anweisung ermittelt. So können wir uns z.B. die Performance einer *list comprehension* ausgeben lassen mit:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "28.1 μs ± 223 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n" ] } ], "source": [ "%timeit L = [n**2 for n in range(1000)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Der Vorteil von `%timeit` ist, dass bei kurzen Befehlen automatisch mehrere Läufe ausgeführt werden, um robustere Ergebnisse zu erzielen. Bei mehrzeiligen Anweisungen wird durch Hinzufügen eines zweiten `%`-Zeichens eine Zellenmagie erzeugt, die mehrere Eingabezeilen verarbeiten kann. Hier ist zum Beispiel die äquivalente Konstruktion mit einer `for`-Schleife:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "30.3 μs ± 184 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n" ] } ], "source": [ "%%timeit\n", "L = []\n", "for n in range(1000):\n", " L.append(n**2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wir können sofort erkennen, dass die *list comprehension* etwa 10% schneller ist als das entsprechende Äquivalent mit einer `for` Schleife. Ausführlicher beschreiben wir Performance-Messungen und -Optimierungen dann in [Profiling](../../performance/ipython-profiler.ipynb)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code anderer Interpreter ausführen\n", "\n", "IPython verfügt über eine `%%script`-Magie, mit der ihr eine Zelle in einem Unterprozess eines Interpreters auf eurem System ausführen könnt, z.B. `bash`, `ruby`, `perl`, `zsh`, `R` usw. Dies kann auch ein eigenes Skript sein, das Eingaben in ` stdin` erwartet. Hierzu wird einfach eine Pfadangabe oder ein Shell-Befehl an das Programm übergeben, das in der `%%script`-Zeile angegeben ist. Der Rest der Zelle wird von diesem Skript ausgeführt, `stdout` oder `err` aus dem Unterprozess erfasst und angezeigt." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ruby 3.3.5\n" ] } ], "source": [ "%%ruby\n", "puts \"Ruby #{RUBY_VERSION}\"" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/opt/homebrew/bin/bash\n" ] } ], "source": [ "%%bash\n", "echo \"$BASH\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ihr könnt `stdout` und `err` aus diesen Unterprozessen in Python-Variablen erfassen:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "%%bash --out output --err error\n", "echo \"stdout\"\n", "echo \"stderr\" >&2" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "stderr\n", "\n", "stdout\n", "\n" ] } ], "source": [ "print(error)\n", "print(output)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Standard-`script`-Magie konfigurieren\n", "\n", "Die Liste der Aliase für die `script`-Magie ist konfigurierbar. Standardmäßig können ggf. einige gängige Interpreter verwendet werden. Ihr könnt jedoch in `ipython_config.py` auch eigene Interpreter angeben:\n", "```\n", "c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']\n", "c.ScriptMagics.script_paths = {'myprogram': '/path/to/myprogram'}\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hilfe-Funktionen: `?`, `%magic` und `%lsmagic`\n", "\n", "Wie normale Python-Funktionen verfügen auch die magischen IPython-Funktionen über *docstrings*, auf die einfach zugegriffen werden können. Um z.B. die Dokumentation der `%timeit`-Magie zu lesen, gebt einfach Folgendes ein:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[0;31mDocstring:\u001b[0m\n", "Time execution of a Python statement or expression\n", "\n", "**Usage, in line mode:**\n", "\n", " %timeit [-n -r [-t|-c] -q -p

-o] statement\n", "\n", "**or in cell mode:**\n", "\n", " %%timeit [-n -r [-t|-c] -q -p

-o] setup_code\n", "…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%timeit?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Auf die Dokumentation für andere Funktionen kann auf ähnliche Weise zugegriffen werden. Um auf eine allgemeine Beschreibung der verfügbaren `%magic`-Funktionen einschließlich einiger Beispiele zuzugreifen, könnt ihr Folgendes eingeben:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\n", "IPython's 'magic' functions\n", "===========================\n", "\n", "The magic function system provides a series of functions which allow you to\n", "control the behavior of IPython itself, plus a lot of system-type\n", "features. There are two kinds of magics, line-oriented and cell-oriented.\n", "\n", "Line magics are prefixed with the % character and work much like OS\n", "command-line calls: they get as an argument the rest of the line, where\n", "arguments are passed without parentheses or quotes. For example, this will\n", "time the given statement::\n", "\n", " %timeit range(1000)\n", "\n", "Cell magics are prefixed with a double %%, and they are functions that get as\n", "an argument not only the rest of the line, but also the lines below it in a\n", "separate argument. These magics are called with two arguments: the rest of the\n", "call line and the body of the cell, consisting of the lines below the first.\n", "For example::\n", "\n", " %%timeit x = numpy.random.randn((100, 100))\n", " numpy.linalg.svd(x)\n", "\n", "will time the execution of the numpy svd routine, running the assignment of x\n", "as part of the setup phase, which is not timed.\n", "…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%magic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Um schnell eine Liste aller verfügbaren `magic`-Funktionen zu erhalten, gebt Folgendes ein:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "application/json": { "cell": { "!": "OSMagics", "HTML": "Other", "SVG": "Other", "bash": "Other", "capture": "ExecutionMagics", "code_wrap": "ExecutionMagics", "debug": "ExecutionMagics", "file": "Other", "html": "DisplayMagics", "javascript": "DisplayMagics", "js": "DisplayMagics", "latex": "DisplayMagics", "markdown": "DisplayMagics", "perl": "Other", "prun": "ExecutionMagics", "pypy": "Other", "python": "Other", "python2": "Other", "python3": "Other", "ruby": "Other", "script": "ScriptMagics", "sh": "Other", "svg": "DisplayMagics", "sx": "OSMagics", "system": "OSMagics", "time": "ExecutionMagics", "timeit": "ExecutionMagics", "writefile": "OSMagics" }, "line": { "alias": "OSMagics", "alias_magic": "BasicMagics", "autoawait": "AsyncMagics", "autocall": "AutoMagics", "automagic": "AutoMagics", "autosave": "KernelMagics", "bookmark": "OSMagics", "cat": "Other", "cd": "OSMagics", "clear": "KernelMagics", "code_wrap": "ExecutionMagics", "colors": "BasicMagics", "conda": "PackagingMagics", "config": "ConfigMagics", "connect_info": "KernelMagics", "cp": "Other", "debug": "ExecutionMagics", "dhist": "OSMagics", "dirs": "OSMagics", "doctest_mode": "BasicMagics", "ed": "Other", "edit": "KernelMagics", "env": "OSMagics", "gui": "BasicMagics", "hist": "Other", "history": "HistoryMagics", "killbgscripts": "ScriptMagics", "ldir": "Other", "less": "KernelMagics", "lf": "Other", "lk": "Other", "ll": "Other", "load": "CodeMagics", "load_ext": "ExtensionMagics", "loadpy": "CodeMagics", "logoff": "LoggingMagics", "logon": "LoggingMagics", "logstart": "LoggingMagics", "logstate": "LoggingMagics", "logstop": "LoggingMagics", "ls": "Other", "lsmagic": "BasicMagics", "lx": "Other", "macro": "ExecutionMagics", "magic": "BasicMagics", "mamba": "PackagingMagics", "man": "KernelMagics", "matplotlib": "PylabMagics", "micromamba": "PackagingMagics", "mkdir": "Other", "more": "KernelMagics", "mv": "Other", "notebook": "BasicMagics", "page": "BasicMagics", "pastebin": "CodeMagics", "pdb": "ExecutionMagics", "pdef": "NamespaceMagics", "pdoc": "NamespaceMagics", "pfile": "NamespaceMagics", "pinfo": "NamespaceMagics", "pinfo2": "NamespaceMagics", "pip": "PackagingMagics", "popd": "OSMagics", "pprint": "BasicMagics", "precision": "BasicMagics", "prun": "ExecutionMagics", "psearch": "NamespaceMagics", "psource": "NamespaceMagics", "pushd": "OSMagics", "pwd": "OSMagics", "pycat": "OSMagics", "pylab": "PylabMagics", "qtconsole": "KernelMagics", "quickref": "BasicMagics", "recall": "HistoryMagics", "rehashx": "OSMagics", "reload_ext": "ExtensionMagics", "rep": "Other", "rerun": "HistoryMagics", "reset": "NamespaceMagics", "reset_selective": "NamespaceMagics", "rm": "Other", "rmdir": "Other", "run": "ExecutionMagics", "save": "CodeMagics", "sc": "OSMagics", "set_env": "OSMagics", "store": "StoreMagics", "sx": "OSMagics", "system": "OSMagics", "tb": "ExecutionMagics", "time": "ExecutionMagics", "timeit": "ExecutionMagics", "unalias": "OSMagics", "unload_ext": "ExtensionMagics", "uv": "PackagingMagics", "who": "NamespaceMagics", "who_ls": "NamespaceMagics", "whos": "NamespaceMagics", "xdel": "NamespaceMagics", "xmode": "BasicMagics" } }, "text/plain": [ "Available line magics:\n", "%alias %alias_magic %autoawait %autocall %automagic %autosave %bookmark %cat %cd %clear %code_wrap %colors %conda %config %connect_info %cp %debug %dhist %dirs %doctest_mode %ed %edit %env %gui %hist %history %killbgscripts %ldir %less %lf %lk %ll %load %load_ext %loadpy %logoff %logon %logstart %logstate %logstop %ls %lsmagic %lx %macro %magic %mamba %man %matplotlib %micromamba %mkdir %more %mv %notebook %page %pastebin %pdb %pdef %pdoc %pfile %pinfo %pinfo2 %pip %popd %pprint %precision %prun %psearch %psource %pushd %pwd %pycat %pylab %qtconsole %quickref %recall %rehashx %reload_ext %rep %rerun %reset %reset_selective %rm %rmdir %run %save %sc %set_env %store %sx %system %tb %time %timeit %unalias %unload_ext %uv %who %who_ls %whos %xdel %xmode\n", "\n", "Available cell magics:\n", "%%! %%HTML %%SVG %%bash %%capture %%code_wrap %%debug %%file %%html %%javascript %%js %%latex %%markdown %%perl %%prun %%pypy %%python %%python2 %%python3 %%ruby %%script %%sh %%svg %%sx %%system %%time %%timeit %%writefile\n", "\n", "Automagic is ON, % prefix IS NOT needed for line magics." ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%lsmagic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ihr könnt auch einfach eure eigenen `magic`-Funktionen definieren. Weitere Informationen hierzu erhaltet ihr unter [Defining custom magics](https://ipython.readthedocs.io/en/stable/config/custommagics.html)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.13 Kernel", "language": "python", "name": "python313" }, "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.13.0" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }