set environment variable in python script

前端 未结 4 1163
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-27 15:26

I have a bash script that sets an environment variable an runs a command

LD_LIBRARY_PATH=my_path
sqsub -np $1 /homedir/anotherdir/executable
<
相关标签:
4条回答
  • 2020-11-27 15:34

    You can add elements to your environment by using

    os.environ['LD_LIBRARY_PATH'] = 'my_path'
    

    and run subprocesses in a shell (that uses your os.environ) by using

    subprocess.call('sqsub -np ' + var1 + '/homedir/anotherdir/executable', shell=True)
    
    0 讨论(0)
  • 2020-11-27 15:36

    There are many good answers here but you should avoid at all cost to pass untrusted variables to subprocess using shell=True as this is a security risk. The variables can escape to the shell and run arbitrary commands! If you just can't avoid it at least use python3's shlex.quote() to escape the string (if you have multiple space-separated arguments, quote each split instead of the full string).

    shell=False is always the default where you pass an argument array.

    Now the safe solutions...

    Method #1

    Change your own process's environment - the new environment will apply to python itself and all subprocesses.

    os.environ['LD_LIBRARY_PATH'] = 'my_path'
    command = ['sqsub', '-np', var1, '/homedir/anotherdir/executable']
    subprocess.check_call(command)
    

    Method #2

    Make a copy of the environment and pass is to the childen. You have total control over the children environment and won't affect python's own environment.

    myenv = os.environ.copy()
    myenv['LD_LIBRARY_PATH'] = 'my_path'
    command = ['sqsub', '-np', var1, '/homedir/anotherdir/executable']
    subprocess.check_call(command, env=myenv)
    

    Method #3

    Unix only: Execute env to set the environment variable. More cumbersome if you have many variables to modify and not portabe, but like #2 you retain full control over python and children environments.

    command = ['env', 'LD_LIBRARY_PATH=my_path', 'sqsub', '-np', var1, '/homedir/anotherdir/executable']
    subprocess.check_call(command)
    

    Of course if var1 contain multiple space-separated argument they will now be passed as a single argument with spaces. To retain original behavior with shell=True you must compose a command array that contain the splitted string:

    command = ['sqsub', '-np'] + var1.split() + ['/homedir/anotherdir/executable']
    
    0 讨论(0)
  • 2020-11-27 15:41

    Compact solution (provided you don't need other environment variables):

    call('sqsub -np {} /homedir/anotherdir/executable'.format(var1).split(),
          env=dict(LD_LIBRARY_PATH=my_path))
    

    Using the env command line tool:

    call('env LD_LIBRARY_PATH=my_path sqsub -np {} /homedir/anotherdir/executable'.format(var1).split())
    
    0 讨论(0)
  • 2020-11-27 15:55

    bash:

    LD_LIBRARY_PATH=my_path
    sqsub -np $1 /path/to/executable
    

    Similar, in Python:

    import os
    import subprocess
    import sys
    
    os.environ['LD_LIBRARY_PATH'] = "my_path" # visible in this process + all children
    subprocess.check_call(['sqsub', '-np', sys.argv[1], '/path/to/executable'],
                          env=dict(os.environ, SQSUB_VAR="visible in this subprocess"))
    
    0 讨论(0)
提交回复
热议问题