24

I am trying to run both Python and bash commands in a bash script. In the bash script, I want to execute some bash commands enclosed by a Python loop:

#!/bin/bash

python << END
for i in range(1000):
    #execute‬ some bash command such as echoing i
END

How can I do this?

0

3 Answers 3

41

Use subprocess, e.g.:

import subprocess
# ...

subprocess.call(["echo", i])

There is another function like subprocess.call: subprocess.check_call. It is exactly like call, just that it throws an exception if the command executed returned with a non-zero exit code. This is often feasible behaviour in scripts and utilities.

subprocess.check_output behaves the same as check_call, but returns the standard output of the program.


If you do not need shell features (such as variable expansion, wildcards, ...), never use shell=True (shell=False is the default). If you use shell=True then shell escaping is your job with these functions and they're a security hole if passed unvalidated user input.

The same is true of os.system() -- it is a frequent source of security issues. Don't use it.

Sign up to request clarification or add additional context in comments.

4 Comments

Why is not recommendable to use import os?
@LuisRamonRamirezRodriguez, os.system() provides less control than the subprocess.Popen interface -- most importantly, it provides no way to pass data out-of-band from code (or to provide a literal argv array), making it hard to avoid shell injection vulnerabilities.
@dom0, shell=True is the wrong thing for your subprocess.call(["echo", i], shell=True) example: The shell script that's run is just echo, with no arguments, and the i is passed as an argument to the shell that the script doesn't refer to.
I edited the answer so as to propose the secure way first.
18

Look in to the subprocess module. There is the Popen method and some wrapper functions like call.

  • If you need to check the output (retrieve the result string):

    output = subprocess.check_output(args ....)
    
  • If you want to wait for execution to end before proceeding:

    exitcode = subprocess.call(args ....)
    
  • If you need more functionality like setting environment variables, use the underlying Popen constructor:

    subprocess.Popen(args ...)
    

Remember subprocess is the higher level module. It should replace legacy functions from OS module.

Comments

1

I used this when running from my IDE (PyCharm).

import subprocess

subprocess.check_call('mybashcommand', shell=True)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.