IPython pimpen

Gute Links und Tutorials könnt ihr hier posten.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Naja, vielleicht nicht direkt ein Tutorial, eher eine Art Anleitung/Erfahrungsbericht. In dieses Forum passt es aber wohl noch am besten rein.

Also, angefangen hat alles als ich auf Kommandozeilenoptionen zum Verändern des IPython-Prompts gestoßen bin. Ich sehe nämlich echt keinen Mehrwert darin, dass ein toller Zähler mitläuft, der sich stetig erhöht, wenn man einen Befehl abgeschickt hat. Mir ist der Prompt der ganz "normalen" Python-Shell viel lieber.

Im Zuge dessen wurde mir bewusst (und jetzt fallt bitte nicht vom Stuhl), dass man IPython ja konfigurieren kann - und das nicht zu knapp. Die Dateien finden sich unter Linux sinnigerweise im Verzeichnis `~/.ipython`.

Ich picke mir jetzt nur ein paar Punkte aus der Vorlage `ipythonrc` raus. Eben jene, die ich als verändernswert für mich erachtete. Die Datei selbst wird in den integrierten Kommentaren als deprecated bezeichnet. Man solle das neuere Interface - eine "echte" Python-Datei - benutzen. Da dort aber nicht soviele Beispiele drin sind und ich zu faul gewesen bin, die Befehle auf die andere API zu übertragen, widme ich mich wider der Empfehlung erstmal der besagten Datei. Ich gehe im Folgenden davon aus, dass der interessierte Leser jetzt die Datei im Editor aufgemacht hat und die Suchfunktion zum Auffinden der Punkte nutzen wird. :)

Das erste ist `confirm_exit` (bei mir in Zeile 196). Dieses ist halt die Nachfrage, ob denn wirklich beendet werden soll. Ich habe den Wert von 1 auf 0 gesetzt, weil ich sowas nicht brauche.

Und nun kommen wir auch schon zum Prompt. Es gibt `prompt_in1` und `prompt_in2`, wobei letzteres die berühmten 3 Punkte (`...`) sind, wenn man innerhalb einer Verschachtelung ist. Diese sehen bei mir jetzt so aus:

Code: Alles auswählen

# Prompt strings

# Most bash-like escapes can be used to customize IPython's prompts, as well as
# a few additional ones which are IPython-specific.  All valid prompt escapes
# are described in detail in the Customization section of the IPython HTML/PDF
# manual.

# Use \# to represent the current prompt number, and quote them to protect
# spaces.
#prompt_in1 'In [\#]: '
prompt_in1 '\C_Normal>>> '

# \D is replaced by as many dots as there are digits in the
# current value of \#.
#prompt_in2 '   .\D.: '
prompt_in2 '\C_Normal... '
Die jeweils alte Version habe ich zur Sicherheit immer auskommentiert, damit sie erhalten bleibt. Das `\C` sagt IPython, dass jetzt eine Farbangabe kommt. Die Standardfarben, die eine Unix-Shell so machen kann, sind nämlich mit den zugehörigen Escape-Sequenzen in der coloransi.py hinterlegt. `Normal` sagt ihm, dass keine Farbe bzw der Defaultwert der Shell benutzt werden soll - also hier: kein grüner Prompt.

Danach kommt noch der Prompt für den Returnwert nach einem Befehl, welchen ich gemäß der Standardshell von Python überhaupt nicht gesondert benannt haben möchte:

Code: Alles auswählen

#prompt_out 'Out[\#]: '
prompt_out ''
Anschließend sage ich mit `prompts_pad_left 0`, dass ich die Ausgabe *nicht* unter dem ersten Zeichen der Eingabe (also eingerückt) haben möchte.

Ich möchte ebenfalls keine extra neue Zeile nach einer Ausgabe haben, also: `nosep 1`.

Dann noch ein paar Einstellungen für `readline`. Ich möchte, dass er meine angefangene Eingabe nach einem Druck auf die Tab-Taste mit dem erstmöglichen Vorschlag komplettiert und im Zweifel so oft auf `Tab` drücken bis ich das richtige habe. Also so herum auskommentiert:

Code: Alles auswählen

#readline_parse_and_bind tab: complete
readline_parse_and_bind tab: menu-complete
Mit Strg-L erhalte ich eine Liste der Vorschläge:

Code: Alles auswählen

readline_parse_and_bind "\C-l": possible-completions
So, das war's für diese Datei. Kommen wir zum neueren Interface: `ipy_user_conf.py`. Dort habe ich eigentlich nur eine Änderung vorgenommen:

Code: Alles auswählen

import readline
readline.parse_and_bind('set completion-query-items 1000')
readline.parse_and_bind('set page-completions no')
Das erste sagt ihm, ab wann er seine `List all items`-Frage stellen soll. Am liebsten gar nicht, also mal die Vorgabe von 1000 Items übernommen. Das zweite besagt, ob in Fällen, wo nicht alle Vorschläge auf eine Seite passen der Pager (bei mir: `more`) benutzt werden soll. Ich finde das eher unpraktisch und hab die Option daher ausgeschaltet.

So, dass war's auch schon. Eventuell hat es ja jemandem geholfen... :)
BlackJack

@snafu: Der Mehrwert von dem Zähler ist, dass man weiss an welche Nummer das jeweilige Ergebnis gebunden ist. Wusstest Du das nicht, oder brauchst Du das nicht? Ich finde das nämlich manchmal sehr praktisch wenn man verschiedene Sachen ausprobiert oder ausrechnet, dass man jederzeit auf alte Zwischenergebnisse zurückgreifen kann.

Code: Alles auswählen

In [17]: 42 * 23
Out[17]: 966

In [18]: sqrt(4711)
Out[18]: 68.636724863588881

In [19]: _17 + _18
Out[19]: 1034.6367248635888
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Das ist mir neu gewesen! Danke für den Tipp :-) Ist echt praktisch. Allerdings sind die Nummern imho auch praktisch, wenn man ein kleine Session postet und sich bei der Erklärung auf die einzelnen "Schritte" bezieht.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@BJ: Kannte ich noch nicht, weiß ich aber auch nicht, ob ich das brauche.
Antworten