87

I have a string representing a path. Because this application is used on Windows, OSX and Linux, we've defined environment variables to properly map volumes from the different file systems. The result is:

"$C/test/testing"

What I want to do is evaluate the environment variables in the string so that they're replaced by their respective volume names. Is there a specific command I'm missing, or do I have to take os.environ.keys() and manually replace the strings?

3 Answers 3

138

Use os.path.expandvars to expand the environment variables in the string, for example:

>>> os.path.expandvars('$C/test/testing')
'/stackoverflow/test/testing'
Sign up to request clarification or add additional context in comments.

3 Comments

Its a pity there's no way to escape a $ to stop some variables being expanded. For example, $C/test/$$ACTION or $C/test/\$ACTION to produce the string '/stackoverflow/test/$ACTION
@JulianMann If you define DOLLARSIGN as a variable, you can use ${DOLLARSIGN} where you want to use a literal dollar sign.
Note that this will not expand variables that are not set. If you want them to expand into empty values (like Bash does), you may want to use string.Template instead.
11

In Python 3 you can do:

'{VAR}'.format(**os.environ)

for example

>>> 'hello from {PWD}'.format(**os.environ)
hello from /Users/william

2 Comments

Great idea! No need to create variables like DOLLAR='$'. Thanks.
For clarification, '{VAR1} and {VAR2}'.format(**os.environ) passes the list of variables present in the string to os.environ, which is passed to the _Environ constructor, and the double asterisk unpacks the values returned via the __getitem__ indexer, which effectively performsos.environ["VAR"] for each variable. I had to search through a bunch of documentation to understand why this worked. I could be slightly wrong on some of this, but that's the gist.
4

The os.path.expandvars solution will not expand variables that aren't set.

If you want unset variables to be expanded to empty values (like the shell does), you can use string.Template, example:

import os
from string import Template
from collections import defaultdict

def expand_posix_vars(posix_expr, context):
    env = defaultdict(lambda: '')
    env.update(context)
    return Template(posix_expr).substitute(env)

conf_str = "${PREFIX}something"

assert "something" == expand_posix_vars(conf_str, {})
assert "hellosomething" == expand_posix_vars(conf_str, {"PREFIX": "hello"})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.