5

After years of bash scripting I've been given the task of modifying a python script to have it call a shell script when certain conditions are met. That part wasn't too bad, but now I'm trying to also send this shell script a variable from within the python script and I'm getting lost.

The shell script takes stdin, which is where I'm trying to place the value of the python variable, which is just an interger.

my code (so far) looks like this:

if VAR > NUMBER: import os bashCommand = "echo something | /path/to/script --args" os.system(bashCommand) 

and it works just fine. But what I am looking to do is make os.system(bashCommand) an equivalent of:

echo $VAR | /path/to/script --args 

or even

echo 'some text' $VAR | /path/to/script --args 

given the way os.system appears to work though it seems I'm approaching this completely wrong.

So I guess my question is how can I pass the value of VAR to bashCommand, preferably as stdin?

    4 Answers 4

    6

    Don't use os.system(), it is deprecated in favor of subprocess module.

    In your case you can use subprocess module directly and its better to not use the shell=True parameter as this is not safe to run commands directly into the shell. All the functionalities you need here like pipe can be emulated by the subprocess module.

    Lets take this example :

    import subprocess var = 'foobar' first = subprocess.Popen(['/bin/echo', var], stdout=subprocess.PIPE) second = subprocess.Popen(['bash', '/path/to/script', '--args'], stdin=first.stdout) 

    we have defined a varible var, then we have used the subprocess.Popen class to get the value of var using /bin/echo and then sent this value to the pipe. The first is an object of subprocess.Popen class.

    Then we have used the STDOUT of first as STDIN of second via pipe and executed the bash script accordingly.

    If you want to save the output of a command as a string use subprocess.check_output function instead e.g. :

    second = subprocess.check_output(['bash', '/path/to/script', '--args'], stdin=first.stdout) 

    Read the offical documentation of subprocess module to get more idea.

    6
    • This is great information and I think I could use it. The one thing I think I should mention though is that 'VAR' is a variable (integer) defined by the python script (that is to call the shell script) so we may not need to echo it, right? since python already knows its value.CommentedSep 3, 2015 at 20:00
    • @kadamwolfe Yeah..you can use it directly then as I have used in the second object generation..I was just pointing out the processes in my sample script..fit it to meet your need :)
      – heemayl
      CommentedSep 3, 2015 at 20:04
    • nice. so something like.... subprocess.Popen(['bash', '/path/to/script', '--args'], stdin="some text" VAR) ?CommentedSep 3, 2015 at 20:06
    • @kadamwolfe I probably have misunderstood your point, you can't directly use a string as STDIN as it does not have fileno attribute..you can combine the two into a simple one liner: subprocess.Popen(['bash', '/path/to/script'], stdin=subprocess.Popen(['/bin/echo', var], stdout=subprocess.PIPE).stdout) ,if its a one time run then you can consider subprocess.call instead of subprocess.Popen..
      – heemayl
      CommentedSep 3, 2015 at 20:21
    • While I do appreciate the help, I'm not sure it resolves my issue. I'm checking if a variable's value is greater than another and if so, echo that variable's value to a shell script (preferably pre-pended by a text string. if VAR > NUMBER: <echo text string + VAR's value to /path/to/script --args>CommentedSep 3, 2015 at 20:40
    3

    Python doesn't expand variables in strings in the same way as bash. If you have VAR in python and want to pass that to bash you could do

    subprocess.call('echo {} | /path/to/script --args'.format(VAR), shell=True) 

    if VAR in python holds the name of a bash variable you want to expand you could do similar:

    subprocess.call('echo "${}" | /path/to/script --args'.format(VAR), shell=True) 
    2
    • I'm not sure of the best-practice/security issues of using "shell=' but this worked for me. Marking resolved.CommentedSep 4, 2015 at 14:44
    • This is a bad practice. If you use shell=true, you should escape VAR with shlex.. so it will be : .... .format(shlex.quote(VAR))
      – Gonzalo
      CommentedFeb 19, 2021 at 13:36
    0

    Calling os.system() is deprecated, though still valid. That functionality may be going away in the future (probably will be), so you might want to give serious consideration to refactoring those calls with the subprocess module, which has an very easy way to send data to a subprocess's STDIN and read from its STDOUT. https://docs.python.org/2/library/subprocess.html

      0

      I think the good practice is:

      var = subprocess.Popen(['/bin/echo', var], stdout=subprocess.PIPE) second = subprocess.Popen(['bash', '/path/to/script', '--args'],stdin=var.stdout, stdout=subprocess.PIPE) var.stdout.close() output = second.communicate()[0] var.wait() 

        You must log in to answer this question.

        Start asking to get answers

        Find the answer to your question by asking.

        Ask question

        Explore related questions

        See similar questions with these tags.