Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

running multiple bash commands with subprocess

If I run echo a; echo b in bash the result will be that both commands are run. However if I use subprocess then the first command is run, printing out the whole of the rest of the line. The code below echos a; echo b instead of a b, how do I get it to run both commands?

import subprocess, shlex def subprocess_cmd(command):     process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)     proc_stdout = process.communicate()[0].strip()      print proc_stdout  subprocess_cmd("echo a; echo b") 
like image 980
Paul Avatar asked Jul 19 '13 09:07

Paul


People also ask

How do I run multiple commands in Python shell?

Run Multiple Commands at Once In Linux: You can use the | operator to concatenate two commands. The first command will list the files and folders in the directory, and the second command will print the output All the files and folders are listed.

Why are shells true in subprocess?

Setting the shell argument to a true value causes subprocess to spawn an intermediate shell process, and tell it to run the command. In other words, using an intermediate shell means that variables, glob patterns, and other special shell features in the command string are processed before the command is run.

What is subprocess Popen?

The subprocess module defines one class, Popen and a few wrapper functions that use that class. The constructor for Popen takes arguments to set up the new process so the parent can communicate with it via pipes. It provides all of the functionality of the other modules and functions it replaces, and more.


2 Answers

You have to use shell=True in subprocess and no shlex.split:

import subprocess  command = "echo a; echo b"  ret = subprocess.run(command, capture_output=True, shell=True)  # before Python 3.7: # ret = subprocess.run(command, stdout=subprocess.PIPE, shell=True)  print(ret.stdout.decode()) 

returns:

a b 
like image 97
bougui Avatar answered Oct 03 '22 05:10

bougui


I just stumbled on a situation where I needed to run a bunch of lines of bash code (not separated with semicolons) from within python. In this scenario the proposed solutions do not help. One approach would be to save a file and then run it with Popen, but it wasn't possible in my situation.

What I ended up doing is something like:

commands = ''' echo "a" echo "b" echo "c" echo "d" '''  process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE) out, err = process.communicate(commands) print out 

So I first create the child bash process and after I tell it what to execute. This approach removes the limitations of passing the command directly to the Popen constructor.

like image 35
admenva Avatar answered Oct 03 '22 05:10

admenva