2

I have file called . /home/test.sh (the space between the first . and / is intentional) which contains some environmental variables. I need to load this file and run the .py. If I run the command manually first on the Linux server and then run python script it generates the required output. However, I want to call . /home/test.sh from within python to load the profile and run rest of the code. If this profile is not loaded python scripts runs and gives 0 as an output.

The call

subprocess.call('. /home/test.sh',shell=True)

runs fine but the profile is not loaded on the Linux terminal to execute python code and give the desired output.

Can someone help?

loudmummer
  • 544
  • 3
  • 19
Raj
  • 33
  • 5
  • Does the `test.sh` print anything or just set environment variables? I have an idea that if it doesn't print anything, you could run a shell command that runs it and then runs `env`, and then you can capture that output in python and use it to set environment variables in python. But it won't work if test.sh prints anything. – alani Sep 12 '20 at 04:59
  • if the real use case is to set env variables, create a file .env and add all your env variables there – senthil balaji Sep 12 '20 at 05:02
  • more on picking up env variables, https://stackoverflow.com/questions/4906977/how-to-access-environment-variable-values – senthil balaji Sep 12 '20 at 05:03
  • I just wanted to point out that there's no way you're going to run a Python script that changes environment variables in a terminal environment. Maybe you're not expecting that, but I just thought I'd point this out to make sure that's not what you're trying to do. I worry because of the '.' in the command `subprocess.call('. /home/test.sh,shell=True)`. That suggests that maybe you're trying to change the environment that Python is running in. That is never going to work. – CryptoFool Sep 12 '20 at 05:16

1 Answers1

2

Environment variables are not inherited directly by the parent process, which is why your simple approach does not work.

If you are trying to pick up environment variables that have been set in your test.sh, then one thing you could do instead is to use env in a sub-shell to write them to stdout after sourcing the script, and then in Python you can parse these and set them locally.

The code below will work provided that test.sh does not write any output itself. (If it does, then what you could do to work around it would be to echo some separator string afterward sourcing it, and before running the env, and then in the Python code, strip off the separator string and everything before it.)

import subprocess
import os

p = subprocess.Popen(". /home/test.sh; env -0", shell=True, 
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)

out, _ = p.communicate()

for varspec in out.decode().split("\x00")[:-1]:
    pos = varspec.index("=")
    name = varspec[:pos]
    value = varspec[pos + 1:]
    os.environ[name] = value

# just to test whether it works - output of the following should include
# the variables that were set
os.system("env")

It is also worth considering that if all that you want to do is set some environment variables every time before you run any python code, then one option is just to source your test.sh from a shell-script wrapper, and not try to set them inside python at all:

#!/bin/sh
. /home/test.sh
exec "/path/to/your/python/script $@"

Then when you want to run the Python code, you run the wrapper instead.

alani
  • 12,573
  • 2
  • 13
  • 23
  • @Raj If this has answered your question (you say that it worked for you), but you now have additional requirements, then the thing to do is to ask another question if you need help. I believe that it will allow you to ask a question every 90 minutes. – alani Sep 12 '20 at 07:03
  • Thanks alani.It worked using the subprocess script which you have shared but the other challenge I have is I need to load another .sh(profile/environment variable) to get an output. Currently it loads the below one giving us an output for servers but need to load another profile(.sh) to get an output for the servers in python script. In that it gives complete output what I was expecting. Any help would be much appreciated? – Raj Sep 12 '20 at 07:06
  • Hi @Raj, This is what I mean about asking another question -- and then hopefully either myself or someone else will answer. You can always link to this question as part of it, if it helps clarify your next question. But sorry, I don't propose to try to answer that as part of *this* question. – alani Sep 12 '20 at 07:09
  • 1
    Ok Alani will do.It worked and Will create another question. – Raj Sep 12 '20 at 07:19
  • 1
    have created a another question. https://stackoverflow.com/questions/63858465/how-to-call-multiple-home-test-sh-and-home-test1-sh-file-in-python-script – Raj Sep 12 '20 at 08:39
  • Okay, great. I might or might not get a chance to look at it just now, but no doubt other people will be looking also. – alani Sep 12 '20 at 08:40