Search code examples
pythonsubprocess

Why does passing variables to subprocess.Popen not work despite passing a list of arguments?


I have a script which calls another Python script by subprocess.Popen. But since I have arguments stored in variable(s)

servers[server]['address']
servers[server]['port']
servers[server]['pass']

I am unable to perform the command

p = subprocess.Popen(
    ["python mytool.py -a ", servers[server]['address'], "-x", servers[server]['port'], "-p", servers[server]['pass'], "some additional command"],
    shell=True,
    stdout=subprocess.PIPE
)

Solution

  • Drop shell=True. The arguments to Popen() are treated differently on Unix if shell=True:

    import sys
    from subprocess import Popen, PIPE
    
    # populate list of arguments
    args = ["mytool.py"]
    for opt, optname in zip("-a -x -p".split(), "address port pass".split()):
        args.extend([opt, str(servers[server][optname])])
    args.extend("some additional command".split())
    
    # run script
    p = Popen([sys.executable or 'python'] + args, stdout=PIPE)
    # use p.stdout here...
    p.stdout.close()
    p.wait()
    

    Note that passing shell=True for commands with external input is a security hazard, as described by a warning in the docs.