I have a python script that will run a batch script. This batch script sets an environment variable say _BLDPATH. I want to grab this variable in the python script to use that variable later on. The problem is that even though the variable gets set properly when the batch file was executed, the os.getenv does not get me the variable back in python script.
How do I get this to work.

snippet of the code is
import os
os.system("bldroott.bat")
bldpath = os.getenv("_BLDPATH")
print "bld path is ",bldpath

snippet of bldroot.bat
REM ....
REM...
if "%_BLDPATH%" == "" goto SET_BLDPATH
goto DONE

:SET_BLDPATH
set _BLDPATH=C:\Bld607

echo %_BLDPATH%
:DONE

The result when I run the above python script is
bld path is None

Dani AI

Generated

As explains, a child process cannot directly mutate the parent process environment, so running the batch with plain os.system() will never make _BLDPATH suddenly appear in Python. The reliable technique is to run the batch and then emit the variable from the same cmd session, capture that stdout and parse it back into Python.

A robust, cross-version approach uses the Windows cmd /c shell to run the batch and then run set _BLDPATH in the same session. set returns lines like _BLDPATH=C:\Bld607, which are easy to parse. Example:

import subprocess, os

cmd = ['cmd', '/c', 'call', 'bldroott.bat', '&&', 'set', '_BLDPATH']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if isinstance(out, bytes):
    out = out.decode('utf-8', errors='replace')

bldpath = None
for line in out.splitlines():
    if line.startswith('_BLDPATH='):
        bldpath = line.split('=', 1)[1]
        break

if bldpath:
    os.environ['_BLDPATH'] = bldpath  # now available to the current Python process

Notes and troubleshooting

  • Use call so a batch file invoked inside another batch returns control properly.
  • Prefer set _BLDPATH to echo %_BLDPATH%set prints the name/value pair and avoids the “ECHO is off.” ambiguity.
  • If nothing is captured, run the full command manually from a cmd prompt to verify the batch actually sets the variable and that you’re calling the correct file/path.
  • Avoid shell=True with user-supplied data for security; the list form above is safer.

This implements ’s capture idea while addressing the parent/child environment limitation highlighted by and .

Recommended Answers

All 5 Replies

Try this ...

# run an external program and get its output:
import os
prog = "bldroott.bat"
fin, fout = os.popen4(prog)
result = fout.read()
print result

Thanks for the reply.
I have
@echo off
in the batch file so the below code will not return anything in result.
If I have echo on in the batch file then all the lines in the batch file gets dumped to result.
any other clue.

Hi gtselvam,

I hate to say this, but I think what you want to do is impossible due to operating system limitations. If memory serves, the os.system() function call creates a forked environment which is destroyed once the call returns. In other words, suppose you write a python script called which says:

import os
print os.getenv("_SOMEVAR")

Then suppose you call it from within a batch script called execute.bat:

@echo off
set _SOMEVAR=value
python batch.py

If you now run execute.bat, you should see "value" pop up in your output. However, suppose that you now create another python script which does this:

import os
os.system("execute.bat")
print os.getenv("_SOMEVAR")

What do you think will happen? This script calls execute.bat and a forked environment is created. The execute.bat batch file sets _SOMEVAR to "value" within this forked context. Then it calls , which prints out the value of _SOMEVAR. But then, the batch file terminates and its environment is destroyed. When the original script then tries to get the value of _SOMEVAR, it is referring to the original context, where _SOMEVAR was never set. So it prints None.

I think the only choice you have is to alter bldroot.bat and force it to print or output the value you want, then read that in using os.popen(), which is what sneekula was driving at. Alternatively, you could dump the value of _SOMEVAR in a temporary text file, or something. The DOS shell wasn't meant to be used the way you want to use it.

Hope this helps!

I haven't used python to do this, but in Windows it is possible to specify the environment table the child is to use. Thus, if the child modifies its environment, it is modifying something that the parent has direct access to.

Unless someone beats me to it, let me see if I can find how to create a process this way in python. This will, of course, be a windows-specific thing to do...

Alas, it looks like I was mistaken about python... None of the python interfaces to CreateProcess report back changes to the enviornment dictionary...

It looks like printing to stdout and using one of the popen module's functions is your best bet...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.