简体   繁体   中英

How to get the environment variable set by a bash script from inside a python script?

I do have a setenv.sh script which is called at the begining of several others scripts, most of them being bash scripts. Obviously this script does set some enviroment variables, which are user later by these scripts.

Now, the problem is that I want to implement the same behaviour into some python scripts and I discovered that the enviroment of the python script is not updated if you run the setenv.

As I do not want to create another script which calls first the setenv.sh and other this myscript.py --- I am looking for a way to convince python to load these variables (parsing the seteve.h is not an option... as it is more complex).

Here's a little library that does it:

https://github.com/aneilbaboo/shellvars-py

Perhaps try to run env before export and after and than compare the results. Something like this

$ pwd
/tmp/test
$ cat setenv.sh
#!/bin/bash
export test=1234
$ cat test.sh
#!/bin/bash
source /tmp/test/setenv.sh
echo $test
$ ./test.sh
1234
$ python test.py
test=1234
$ cat test.py
#/usr/bin/env python
import os, subprocess
p=subprocess.Popen('env',stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
oldEnv=p.communicate()[0]
p=subprocess.Popen('source /tmp/test/setenv.sh ; env',stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
newEnv=p.communicate()[0]
for newStr in newEnv.split('\n'):
    flag = True
    for oldStr in oldEnv.split('\n'):
        if newStr == oldStr:
            #not exported by setenv.sh
            flag = False
            break
    if flag:
        #exported by setenv.sh
        print newStr

The easiest solution is clearly the one you don't want, which is to create a new script file for each python script.

You could, however, do roughly the equivalent by having the python script call itself. Of course, you need to signal it to not do that on the second invocation, otherwise you'll end up with an infinite (tail) recursion.

The following little "module" (which you can just import, but you should do it right at startup, before anything else) will check to see if the environment variable SETENV has been set, and if so, it will re-issue the python command (to the best of its ability, so it might get things wrong if it wasn't just a simple script execution) after sourcing the file named by SETENV . It lacks lots of error-checking and shouldn't be considered production-ready; rather a proof-of-concept:

# file env_set.py
import os
import sys

if sys.argv[0] and "SETENV" in os.environ:
  setenv = os.environ["SETENV"]
  del os.environ["SETENV"]
  os.execvp("bash", ["bash", "-c",
        "source " + setenv + "; exec python " + sys.argv[0] + ' "${@}"',
        "--"] + sys.argv[1:])

And a little test:

# file test_env_set.py
import env_set

import os
import sys
for name in sys.argv[1:]:
  if name in os.environ:
    print(name + "=" + os.environ[name])
  else:
    print("Undefined: " + name)

# file setenv.sh
export the_answer=42

$ python test_env_set.py SETENV the_answer
Undefined: SETENV
Undefined: the_answer
$ SETENV=setenv.sh python test_env_set.py SETENV the_answer
Undefined: SETENV
the_answer=42

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM