bu0603
bu0603

Reputation: 47

escape ampersand & in string when send as argument python

I have written two python scripts A.py and B.py So B.py gets called in A.py like this:

config_object = {}
with open(config_filename) as data:
  config_object = json.load(data, object_pairs_hook=OrderedDict)
command = './scripts/B.py --config-file={} --token-a={} --token-b={}'.format(promote_config_filename, config_object['username'], config_object['password'])
      os.system(command)

In here config_object['password'] contains & in it. Say it is something like this S01S0lQb1T3&BRn2^Qt3

Now when this value get passed to B.py it gets password as S01S0lQb1T3 So after & whatever it is getting ignored.

How to solve this?

Upvotes: 0

Views: 1119

Answers (2)

tripleee
tripleee

Reputation: 189377

os.system runs a shell. You can escape arbitrary strings for the shell with shlex.quote() ... but a much superior solution is to use subprocess instead, like the os.system documentation also recommends.

subprocess.run(
    ['./scripts/B.py',
     '--config-file={}'.format(promote_config_filename),
     '--token-a={}'.format(config_object['username']),
     '--token-b={}'.format(config_object['password'])])

Because there is no shell=True, the strings are now passed to the subprocess verbatim.

Perhaps see also Actual meaning of shell=True in subprocess

Upvotes: 1

dcc310
dcc310

Reputation: 1076

@tripleee has good suggestions. In terms of why this is happening, if you are running Linux/Unix at least, the & would start a background process. You can search "linux job control" for more info on that. The shortest (but not best) solution is to wrap your special characters in single or double quotes in the final command.

See this bash for a simple example:

$ echo foo&bar
[1] 20054
foo
Command 'bar' not found, but can be installed with:
sudo apt install bar
[1]+  Done                    echo foo

$ echo "foo&bar"
foo&bar

Upvotes: 0

Related Questions