2013-05-14 15 views
5

Mam skrypt, gdzie pewne parametry są ustawione tak:
k.sh:Używanie zmiennych w skrypcie powłoki Python nie działa

export var="value" 
export val2="value2" 

Następnie Mam skrypt Pythona, gdzie Wołam skrypt powłoki i chcesz używać tych zmiennych enviornment
ex1.py:

import subprocess 
import os 
subprocess.call("source k.sh",shell=True) 
print os.environ["var"] 

Ale otrzymuję KeyError Jak mogę użyć tej zmiennej powłoki w moim skrypcie Pythona?

+0

Czy działa z 'os.system' zamiast' subprocess.call'? – SethMMorton

+0

@SethMMorton: Nie, nie działa z os.system – ftw

+0

To nie jest dobry pomysł. Pytanie brzmi, dlaczego próbujesz to zrobić. Co naprawdę chcesz tutaj robić? Po prostu przekaż zmienne z powrotem do rodzica? – cmd

Odpowiedz

1

subprocess.call uruchamia powłokę w nowym procesie, który wywołuje source. Nie ma możliwości modyfikacji środowiska w procesie z procesu potomnego.

+0

Nie jest to całkowicie pomocne. Założę się, że możesz dostać się do otoczenia podprocesu. – Marcin

+0

@Marcin będzie wymagał pomocy od procesu potomnego (np. Drukowania środowiska i odczytywania go z procesu nadrzędnego) lub czegoś bardziej zaangażowanego. Daleko od trywialności, a to z pewnością * nie będzie działać poprzez 'os.environ' w rodzicu. – robertklep

0

Jak zauważył chepner. Część podprocesowa jest uruchamiana indywidualnie. Praca ze zmiennych środowiskowych musi być wykonane przed uruchomieniem skryptu Pythona ..

Na przykład:

C:\Users\anton\Desktop\githubs>echo %x% 
y 

C:\Users\anton\Desktop\githubs>python 
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import os 
>>> os.environ['x'] 
'y' 
>>> 

Sourcing zmienne środowiskowe przed uruchomieniem skryptu będzie przechodzić w dół jednak, lub jeśli wykonanie wielu komendy do wywołania podprocesowego, które również byłyby świetne po tym, jak je skomponowałeś. na przykład:

import subprocess 
import os 
x = subprocess.call("source k.sh",shell=True, STDIN=subprocess.PIPE, STDOUT=subprocess.PIPE) 
y = subprocess.call("echo $var",shell=True, STDIN=x.stdout, STDOUT=subprocess.PIPE) 

Nigdy nie próbowałem tego, jak wspomniano. Źródło przed uruchomieniem.

2

Można pozyskać k.shi uruchomić Python jednolinijkowych wydrukować zawartość os.environ jako JSON. Następnie użyj json.loads przekonwertować wyjście z powrotem do dict w głównym procesie:

import subprocess 
import os 
import json 
PIPE = subprocess.PIPE 
output = subprocess.check_output(
    ". ~/tmp/k.sh && python -c 'import os, json; print(json.dumps(dict(os.environ)))'", 
    shell=True) 
env = json.loads(output) 
print(env["var"]) 

daje

value 
1

Jeśli chcesz ustawić środowisko, a następnie uruchomić skrypt Pythona, dobrze ustawić środowisko i uruchom skrypt Pythona korzystając biegacza:

biegacza:

#! /bin/bash 
. k.sh 
exec ex1.py 

i to wszystko.

ex1.py:

#import subprocess 
import os 
#subprocess.call("source k.sh",shell=True) 
print os.environ["var"] 
0

/u/unutbu już odpowiedział na to pytanie.Jednak Poprawiłem kilka błędów w jego kodzie:

def run_external_script(script): 
    if is_windows(): 
     command = script+" && python -c \"import os; print dict(os.environ)\"" 
    else: 
     command = ". "+ script+" && python -c 'import os; print dict(os.environ)'" 

    output = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True).communicate()[0] 
    r = re.compile('{.*}') 
    m = r.search(output) 
    try: 
     env = eval(m.group(0)) 
    except: 
     error("Something went wrong in " + script) 
     error(output) 
    return env 

Istnieje kilka małych różnic:

  • Ten kod działa zarówno na Windows/Linux
  • Wymieniłem subprocess.check_output z subprocess.call , check_output wymaga Pythona 2.7
  • Po uruchomieniu jego kodu, wyjście ze skryptu również zostanie wydrukowane w zmiennych wyjściowych. Tak więc użyłem re, aby pobrać słownik pomiędzy dwoma {}, na przykład {'var1' = 1, "var2 '=' x '}.
  • zamiast używać json, użyłem ewalu Pythona. Istnieje ryzyko wstrzyknięcia, więc używaj go na własne ryzyko. taki jak {; exit(1); }
Powiązane problemy