Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute batch file from Python so that it could alter environment of the calling process? [duplicate]

On Windows there's a 3rd party command line tool I would like to use in my python script. Let's say it's foobar.exe located under C:\Program Files (x86)\foobar. Foobar comes with an additional batch file init_env.bat that will set up the shell environment for foobar.exe to run.

I want to write a python script, that will first call init_env.bat once and then foobar.exe multiple times. However, all mechanisms I know of (subprocess, os.system and backticks) seem to spawn a new process for each execution. Therefore, calling init_env.bat is useless, because it does not change the environment of the process in which the python script runs and thus every subsequent call to foobar.exe fails, because it's environment is not set up.

Is it possible to call init_env.bat from python in a way that allows init_env.bat to alter the environment of the calling scripts process?

like image 318
Alexander Tobias Bockstaller Avatar asked Jul 12 '13 12:07

Alexander Tobias Bockstaller


1 Answers

Is it possible to call init_env.bat from python in a way that allows init_env.bat to alter the environment of the calling scripts process?

Not easily, although, if the init_env.bat is really simple, you could attempt to parse it, and make the changes to os.environ yourself.

Otherwise it's much easier to spawn it in a sub-shell, followed by a call to set to output the new environment variables, and parse the output from that.

The following works for me...

init_env.bat

@echo off
set FOO=foo
set BAR=bar

foobar.bat

@echo off
echo FOO=%FOO%
echo BAR=%BAR%

main.py

import sys, os, subprocess


INIT_ENV_BAT = 'init_env.bat'
FOOBAR_EXE = 'foobar.bat'


def init_env():
    vars = subprocess.check_output([INIT_ENV_BAT, '&&', 'set'], shell=True)
    for var in vars.splitlines():
        k, _, v = map(str.strip, var.strip().partition('='))
        if k.startswith('?'):
            continue
        os.environ[k] = v


def main():
    init_env()
    subprocess.check_call(FOOBAR_EXE, shell=True)
    subprocess.check_call(FOOBAR_EXE, shell=True)


if __name__ == '__main__':
    main()

...for which python main.py outputs...

FOO=foo
BAR=bar
FOO=foo
BAR=bar

Note that I'm only using a batch file in place of your foobar.exe because I don't have a .exe file handy which can confirm the environment variables are set.

If you're using a .exe file, you can remove the shell=True clause from the lines subprocess.check_call(FOOBAR_EXE, shell=True).

like image 110
Aya Avatar answered Sep 21 '22 23:09

Aya