Search code examples
pythonlinuxbashpython-2.6

How to read python variables into bash command


I'm writing script to generate Autosys report using Python 2.6, and I would like to pass variables from python script to bash command:

I have 3 variables:

NextMonth, NDNextMonth, Year

When I'm using the command with 1 varibale, it works properly.

    env = os.environ.copy()
env['NextMonth'] = NextMonth
subprocess.call('forecast -J *JobABC_* -M ALL -F "${NextMonth}/01/2020 00:00" -T "${NextMonth}/31/2020 23:59" -h -n > PythonReport1.txt', env=env, shell=True)

In the opposite way, it does not work, date is not valid:

    env = os.environ.copy()
env['NextMonth'] = NextMonth
env['NDNextMonth'] = NDNextMonth
env['Year'] = Year
subprocess.call('forecast -J *JobABC_* -M ALL -F "${NextMonth}/01/${Year}" 00:00" -T "${NextMonth}/${NDNextMonth}/${Year}" 23:59" -h -n > PythonReport1.txt',env=env, shell=True)

Could you please check, how to read those 3 variables into the command? Error: TypeError: execve() arg 3 contains a non-string value


Solution

  • As pointed out in comments, your variables work fine; the problem is that you have spurious double quotes in the string.

    subprocess.call('forecast -J *JobABC_* -M ALL'
        ' -F "${NextMonth}/01/${Year} 00:00"'
        ' -T "${NextMonth}/${NDNextMonth}/${Year} 23:59"'
        ' -h -n > PythonReport1.txt',
        env=env, shell=True)
    

    Notice how there is no closing double quote after either instance of ${Year} because the string does not end there.

    Incidentally, the braces are not particularly useful here; you might as well use $Year etc. But if your task is merely to pass these values from Python to the shell, just do that, using whatever Python string interpolation mechanism you are comfortable with;

    subprocess.call('forecast -J *JobABC_* -M ALL'
        ' -F "{0}/01/{2} 00:00"'
        ' -T "{0}/{1}/{2} 23:59"'
        ' -h -n > PythonReport1.txt'.format(NextMonth, NDNextMonth, Year),
        shell=True)
    

    A much better solution is to avoid the shell entirely. Also, probably use check_call instead of plain old call. See further Running Bash commands in Python.

    import glob
    with open('PythonReport1.txt', 'w') as handle:
        subprocess.check_call(['forecast', '-J'] + glob.glob('*JobABC_*') +
            ['-M', 'ALL', '-F', "{0}/01/{1} 00:00".format(NextMonth, Year),
             '-T', "{0}/{1}/{2} 23:59".format(NextMonth, NDNextMonth, Year),
             '-h', '-n'], stdout=handle)