Vielleicht hast du schon erlebt, dass eine Software um Erlaubnis bittet, deine PATH-Variable zu ändern, oder dass in den Installationshinweisen eines Programms kryptisch steht, du müsstest "deine LD_LIBRARY_PATH-Variable korrekt setzen".
Als Data Scientist kannst du auf weitere Probleme mit Umgebungsvariablen stoßen, wenn du mit deinem Compute-Stack arbeitest (vor allem, wenn du nicht die volle Kontrolle darüber hast, so wie ich). Dieser Beitrag soll entmystifizieren, was eine Umgebungsvariable ist und wie sie im Data-Science-Kontext genutzt wird.
Was ist eine Umgebungsvariable?
Ich erkläre zunächst, was eine Umgebungsvariable ist, und gehe dabei ausführlich auf die Umgebungsvariable PATH ein. Probier die Befehle gerne in deinem Bash-Terminal aus (mit passenden Anpassungen – lies den Text, um zu verstehen, was ich tue!).
Wenn du dich an deinem System anmeldest, zum Beispiel am Terminal deines Rechners oder per SSH auf einem Remote-Server, muss dein Bash-Interpreter wissen, wo er nach bestimmten Programmen suchen soll, etwa nano (dem Texteditor), git (deiner Versionsverwaltung) oder deinem Python-Interpreter. Das steuert die PATH-Variable. Sie legt fest, in welchen Ordnern ausführbare Programme zu finden sind.
Nach historischer Konvention liegen Kommandozeilenprogramme wie nano, which und top im Verzeichnis /usr/bin. (Ebenfalls historisch bedingt ist der Ordner /bin für Software-Binaries gedacht, daher der Name /bin.) Diese Programme werden mit dem Betriebssystem ausgeliefert und benötigen besondere Rechte für Aktualisierungen.
Probier es im Terminal aus:
$ which which
/usr/bin/which
$ which top
/usr/bin/top
Andere Programme werden (aus welchen Gründen auch immer) stattdessen in /bin installiert. ls ist ein Beispiel:
$ which ls
/bin/ls
Wieder andere Programme landen in speziellen Verzeichnissen:
$ which nano
/usr/local/bin/nano
Wie findet dein Bash-Terminal heraus, wo es nachschauen soll? Es nutzt die Umgebungsvariable PATH. Die sieht ungefähr so aus:
$ echo $PATH
/usr/bin:/bin:/usr/local/bin
Das Wichtigste an der PATH-Variable: Sie ist „durch Doppelpunkte getrennt“. Das heißt, jeder Verzeichnispfad ist durch einen Doppelpunkt (:) vom nächsten getrennt. Die Suchreihenfolge deines Bash-Terminals läuft von links nach rechts:
/usr/bin/bin/usr/local/bin
Wenn ich auf meinem Rechner ls eintippe, schaut der Bash-Interpreter zuerst im Verzeichnis /usr/bin nach. Dort findet er ls nicht und geht weiter zum nächsten Ordner, /bin. Da sich ls bei mir unter /bin befindet, wird das Programm von dort ausgeführt.
Du siehst: Das ist extrem flexibel, um deine Arbeitsumgebung anzupassen, kann aber auch frustrierend sein, wenn ein Programm deine PATH-Variable ändert, ohne dass du es mitbekommst.
Moment, kann man die PATH-Variable wirklich ändern? Ja, und es gibt mehrere Wege dafür.
So änderst du die PATH-Variable
In einer Bash-Session
Die erste Methode ist flüchtig, also temporär, und gilt nur für deine aktuelle Bash-Session. Du kannst einen Ordner höher priorisieren, indem du ihn an den Anfang der PATH-Variable „voranstellst“:
$ export PATH=/path/to/my/folder:$PATH
$ echo $PATH
/path/to/my/folder:/usr/bin:/bin:/usr/local/bin
Oder du gibst ihm eine niedrigere Priorität, indem du ihn an das Ende der PATH-Variable „anhängst“:
$ export PATH=$PATH:/path/to/my/folder
$ echo $PATH
/usr/bin:/bin:/usr/local/bin:/path/to/my/folder
Das ist temporär, weil ich es nur in meiner aktuellen Bash-Session exportiere.
bashrc- oder .bash_profile-Datei
Wenn ich die Änderung etwas dauerhafter machen möchte, füge ich sie in meine .bashrc- oder .bash_profile-Datei ein. (Ich empfehle die .bashrc.) Die Datei .bashrc/.bash_profile liegt in deinem Home-Verzeichnis (deine Umgebungsvariable $HOME gibt es an) und wird beim Start deines Bash-Interpreters ausgeführt. Alle Befehle darin werden abgearbeitet. Das heißt, du kannst deine PATH-Variable ändern, indem du in deiner .bashrc einfach Folgendes ergänzt:
...andere Befehle oben...
# /path/to/folder höher priorisieren
export PATH=/path/to/folder:$PATH
# /path/to/other/folder niedriger priorisieren
export PATH=$PATH:/path/to/folder
...andere Befehle unten...
Data Science und die PATH-Umgebungsvariable
Warum ist das für Data Scientists relevant? Wenn du mit Data Science arbeitest, nutzt du vermutlich Python, und dein Interpreter stammt aus der Anaconda-Distribution (sehr zu empfehlen!). Der Anaconda-Installer setzt den Ordner /path/to/anaconda/bin an die Spitze der PATH-Variable. Du hast eventuell weitere Python-Interpreter installiert (z. B. der von Apple). Durch diese PATH-Anpassung wird aber sichergestellt, dass beim Eintippen von python im Bash-Terminal der Python-Interpreter aus der Anaconda-Distribution gestartet wird. Bei mir sieht die PATH nach der Installation so aus:
$ echo $PATH
/Users/ericmjl/anaconda/bin:/usr/bin:/bin:/usr/local/bin
Noch besser: Aktivierte conda-Umgebungen stellen den Pfad zum jeweiligen bin-Ordner der Umgebung vorne an. Für meinen Blog nutze ich zum Beispiel eine Umgebung namens lektor. Also ...
$ echo $PATH
/Users/ericmjl/anaconda/bin:/usr/bin:/bin:/usr/local/bin
$ which python
/Users/ericmjl/anaconda/bin/python
$ source activate lektor
$ echo $PATH
/Users/ericmjl/anaconda/envs/lektor/bin:/Users/ericmjl/anaconda/bin:/usr/bin:/bin:/usr/local/bin
$ which python
/Users/ericmjl/anaconda/envs/lektor/bin/python
Beachte, dass das Bash-Terminal jetzt bevorzugt das Python in der höher priorisierten lektor-Umgebung auswählt.
Wenn du bis hierher mitgegangen bist, siehst du ein paar wichtige Konzepte. Hier die Kurzfassung:
PATHist eine Umgebungsvariable als einfache Textzeichenkette, die der Bash-Interpreter nutzt, um ausführbare Programme zu finden.PATHist durch Doppelpunkte getrennt; Verzeichnisse mit höherer Priorität stehen links, solche mit niedrigerer rechts.PATHlässt sich ändern, indem Verzeichnisse vorne angefügt (prepending) oder hinten angehängt (appending) werden. Das geht temporär in einer Bash-Session perexport-Befehl oder dauerhaft über eineexport-Zeile in.bashrcoder.bash_profile.
Weitere interessante Umgebungsvariablen
Welche anderen Umgebungsvariablen können dir begegnen? Hier eine Auswahl, die du sehen und notfalls selbst korrigieren könntest – besonders, wenn die Admins im Urlaub sind (oder lange brauchen).
Für den allgemeinen Gebrauch solltest du wissen, wo dein HOME-Ordner liegt – unter Linux oft /home/username, unter macOS meist /Users/username. Du findest ihn so heraus:
$ echo $HOME
/Users/ericmjl
Wenn du Python nutzt, ist PYTHONPATH eine nützliche Variable. Sie wird vom Python-Interpreter verwendet und gibt an, wo Python-Module/-Pakete zu finden sind.
Wenn du mit C++-Bibliotheken arbeitest, ist LD_LIBRARY_PATH sehr wichtig. Ich bin darin nicht tief genug drin, um klug darüber zu referieren, darum verweise ich auf diese Website für Best Practices zum Einsatz der Variable LD_LIBRARY_PATH.
Wenn du mit Spark arbeitest, ist die Umgebungsvariable PYSPARK_PYTHON interessant. Sie teilt Spark mit, welches Python sowohl für den Driver als auch für die Worker genutzt werden soll; du kannst bei Bedarf PYSPARK_DRIVER_PYTHON auch getrennt von PYSPARK_PYTHON setzen.
Hacke deine Umgebungsvariablen
Hier wird’s spannend! Folge mit – ein paar Ideen, was du durch geschicktes Setzen deiner Umgebungsvariablen erreichen kannst.
Hack #1: Zugriff auf PyPy ermöglichen. Ich verfolge gelegentlich die Entwicklung von PyPy. Da PyPy aber noch nicht der Standard-Python-Interpreter ist und sich nicht per conda install beziehen lässt, lege ich es in ein eigenes Verzeichnis $HOME/pypy/bin. Damit der PyPy-Interpreter erreichbar ist, muss /path/to/pypy in der PATH-Variable vorhanden sein – aber mit niedrigerer Priorität als mein regulärer CPython-Interpreter.
Hack #2: Zugriff auf andere Sprach-Interpreter/Compiler. Analog zu PyPy. Ich habe einmal Lua’s JIT-Interpreter ausprobiert, um Torch für Deep Learning zu nutzen, und musste dafür einen Pfad in meiner .bashrc ergänzen.
Hack #3: Python-Pakete in dein Home-Verzeichnis installieren. Auf gemeinsamen Linux-Systemen, die das modules-System anstelle von conda-Umgebungen verwenden, kann ein geladenes modulefile mit einer virtuellen Umgebung konfiguriert sein, die du nicht verändern darfst. Wenn du dann ein Paket installieren musst, hilft pip install --user my_pkg_name. Das landet unter $HOME/.local/lib/python-[version]/site-packages/. Achte darauf, dass dein PYTHONPATH $HOME/.local/lib/python-[version]/site-packages mit ausreichend hoher Priorität enthält.
Hack 4: Debugging, wenn etwas schiefgeht. Wenn Fehler auftreten oder sich etwas unerwartet verhält – bei mir wurde einmal nach dem Laden aller Linux-Module der Python-Interpreter nicht korrekt gefunden – kannst du zum Debuggen deine PATH-Variable temporär auf sinnvolle „Defaults“ setzen und diese sourcen. So „resettest“ du die PATH-Variable und kannst beim Debuggen gezielt vorne anhängen oder hinten anfügen.
Lege dazu die folgende Zeile in einer Datei namens .path_default in deinem Home-Verzeichnis ab:
export PATH="" # setzt PATH auf eine leere Zeichenkette zurück.
export PATH=/usr/bin:/bin:/usr/local/bin:$PATH # sinnvolle Defaults; bei Bedarf anpassen.
Nachdem etwas schiefgelaufen ist, kannst du deine PATH-Variable mit dem Befehl "source" zurücksetzen:
$ echo $PATH
/some/complicated/path:/more/complicated/paths:/really/complicated/paths
$ source ~/.path_default
$ echo $PATH
/usr/bin:/bin:/usr/local/bin
Hinweis: Du kannst dieselben Befehle auch direkt interaktiv in deiner Bash-Session ausführen; das kann beim Debuggen ebenfalls helfen.
Fazit
Ich hoffe, dir hat der Artikel gefallen und er gibt dir – hust – einen guten Pfad, wenn du wieder auf Umgebungsvariablen triffst!
