Ich habe ein Skript, das ungefähr so aussieht:
export foo=/tmp/foo
export bar=/tmp/bar
Jedes Mal, wenn ich baue, führe ich 'source init_env' aus (wobei init_env das obige Skript ist), um einige Variablen einzurichten.
Um dasselbe in Python zu erreichen, ließ ich diesen Code laufen,
reg = re.compile('export (?P<name>\w+)(\=(?P<value>.+))*')
for line in open(file):
m = reg.match(line)
if m:
name = m.group('name')
value = ''
if m.group('value'):
value = m.group('value')
os.putenv(name, value)
Aber dann entschied jemand , dass es schön wäre, der init_env
Datei eine Zeile wie die folgende hinzuzufügen :
export PATH="/foo/bar:/bar/foo:$PATH"
Offensichtlich fiel mein Python-Skript auseinander. Ich könnte das Python-Skript ändern, um diese Zeile zu verarbeiten, aber es wird später unterbrochen, wenn jemand eine neue Funktion für die init_env
Datei entwickelt.
Die Frage ist, ob es eine einfache Möglichkeit gibt, einen Bash-Befehl auszuführen und ihn ändern zu lassen os.environ
.
Antworten:
Das Problem bei Ihrem Ansatz ist, dass Sie versuchen, Bash-Skripte zu interpretieren. Zuerst versuchen Sie einfach, die Exportanweisung zu interpretieren. Dann bemerken Sie, dass Leute variable Erweiterung verwenden. Spätere Personen fügen Bedingungen in ihre Dateien ein oder verarbeiten Ersetzungen. Am Ende haben Sie einen ausgewachsenen Bash-Skript-Interpreter mit einer Unmenge von Fehlern. Tu das nicht.
Lassen Sie Bash die Datei für Sie interpretieren und sammeln Sie dann die Ergebnisse.
Sie können es so machen:
Stellen Sie sicher, dass Sie Fehler behandeln, falls bash fehlschlägt
source init_env
oder bash selbst nicht ausgeführt werden kann oder der Unterprozess bash nicht ausführt oder andere Fehler auftreten.Das
env -i
am Anfang der Befehlszeile erstellt eine saubere Umgebung. Das heißt, Sie erhalten nur die Umgebungsvariablen voninit_env
. Wenn Sie die geerbte Systemumgebung möchten, lassen Sie sie wegenv -i
.Weitere Informationen finden Sie in der Dokumentation zum Unterprozess .
Hinweis: Dies erfasst nur Variablen, die mit der
export
Anweisung festgelegt wurden, daenv
nur exportierte Variablen gedruckt werden.Genießen.
Beachten Sie, dass in der Python-Dokumentation angegeben ist , dass Sie die Umgebung
os.environ
direkt bearbeiten sollten, anstatt sie zu verwendenos.putenv()
. Ich halte das für einen Fehler, aber ich schweife ab.quelle
proc.stdout()
ergab das Iterieren über Bytes Bytes, also bekam ich einTypeError
Online.partition()
. Das Konvertieren in einen String mit hatline.decode().partition("=")
das Problem gelöst.['env', '-i', 'bash', '-c', 'source .bashrc && env']
, um mir nur die Umgebungsvariablen zu geben, die von der RC-Datei festgelegt wurdenMit Gurke:
Aktualisiert:
Dies verwendet json, subprocess und explizit / bin / bash (für die Ubuntu-Unterstützung):
quelle
/bin/dash
, die densource
Befehl nicht kennt . Um es unter Ubuntu zu verwenden, müssen Sie es/bin/bash
explizit ausführen , z. B. mithilfe vonpenv = subprocess.Popen(['/bin/bash', '-c', '%s && %s' %(source,dump)], stdout=subprocess.PIPE).stdout
(dies verwendet das neueresubprocess
Modul, das importiert werden muss).Anstatt dass Ihre Python-Skriptquelle das Bash-Skript ist, wäre es einfacher und eleganter, eine Wrapper-Skriptquelle zu haben
init_env
und dann Ihr Python-Skript mit der geänderten Umgebung auszuführen.quelle
bash --rcfile init_env -c ./script.py
Die Antwort von @ lesmana für Python 3 wurde aktualisiert. Beachten Sie, dass durch deren Verwendung
env -i
verhindert wird, dass fremde Umgebungsvariablen gesetzt / zurückgesetzt werden (möglicherweise falsch, da mehrzeilige env-Variablen nicht behandelt werden).quelle
Beispiel für die hervorragende Antwort von @ Brian in einer Funktion:
Ich verwende diese Dienstprogrammfunktion, um aws-Anmeldeinformationen und Docker-ENV-Dateien mit zu lesen
include_unexported_variables=True
.quelle