18

I am trying to execute a shell script(not command) from python:

main.py
-------
from subprocess import Popen

Process=Popen(['./childdir/execute.sh',str(var1),str(var2)],shell=True)

execute.sh
----------

echo $1 //does not print anything
echo $2 //does not print anything

var1 and var2 are some string that I am using as an input to shell script. Am I missing something or is there another way to do it?

Referred: How to use subprocess popen Python

Community
  • 1
  • 1
creativeDrive
  • 245
  • 1
  • 5
  • 13

3 Answers3

19

The problem is with shell=True. Either remove that argument, or pass all arguments as a string, as follows:

Process=Popen('./childdir/execute.sh %s %s' % (str(var1),str(var2),), shell=True)

The shell will only pass the arguments you provide in the 1st argument of Popen to the process, as it does the interpretation of arguments itself. See a similar question answered here. What actually happens is your shell script gets no arguments, so $1 and $2 are empty.

Popen will inherit stdout and stderr from the python script, so usually there's no need to provide the stdin= and stderr= arguments to Popen (unless you run the script with output redirection, such as >). You should do this only if you need to read the output inside the python script, and manipulate it somehow.

If all you need is to get the output (and don't mind running synchronously), I'd recommend trying check_output, as it is easier to get output than Popen:

output = subprocess.check_output(['./childdir/execute.sh',str(var1),str(var2)])
print(output)

Notice that check_output and check_call have the same rules for the shell= argument as Popen.

Community
  • 1
  • 1
micromoses
  • 6,747
  • 2
  • 20
  • 29
  • @user2837135 If it solved your problem, you should accept it (click on the check mark) and maybe consider upvoting as well. – SethMMorton Oct 11 '13 at 21:11
  • `shell=True` should *not* be used in this case but if you use it then you should escape `var1`, `var2` using [`shlex.quote()`](http://docs.python.org/3/library/shlex.html#shlex.quote): `output = check_output("./childdir/execute.sh " + " ".join(pipes.quote(str(v)) for v in [var1, var2]), shell=True)` – jfs Oct 14 '13 at 08:16
  • Note that the type of output is `bytes` and might need to be converted to a `str` before using it, for example like so: `output.decode("utf-8")` – Gogowitsch Dec 29 '18 at 14:44
3

you actually are sending the arguments ... if your shell script wrote a file instead of printing you would see it. you need to communicate to see your printed output from the script ...

from subprocess import Popen,PIPE

Process=Popen(['./childdir/execute.sh',str(var1),str(var2)],shell=True,stdin=PIPE,stderr=PIPE)
print Process.communicate() #now you should see your output
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • 2
    Also, they could use `subprocess.call(['./childdir/execute.sh',str(var1),str(var2)],shell=True)` if all they want to do is see the output. – SethMMorton Oct 11 '13 at 19:44
  • @Joran : I was able to see the shell script output with shell=True, I am able to see $0('./childdir/execute.sh') i.e. the script that is executing, but not the arguments var1, var2.. – creativeDrive Oct 11 '13 at 19:51
  • maybe add a shebang to the top of the shell script ... it might not be running in bash, however I guarantee you are sending the arguments (maybe the arguments are not what you think they are) – Joran Beasley Oct 11 '13 at 19:52
  • @SethMMorton : I tried both the option and I am getting the error (./execute.sh: premission denied). Although I have given execute prev.(chmod +x execute.sh) – creativeDrive Oct 11 '13 at 19:53
  • @Joran I tried with shebang too...to debug, I created 2 small scripts to check this, but when I print process.communicate() it prints (None.[]) – creativeDrive Oct 11 '13 at 20:01
  • Try running following pythscr.py -------------------------------- #!/usr/bin/env python from subprocess import Popen, PIPE var1="1000" var2="2000" print var1 print var2 process=Popen(['bash shellscr.sh',str(var1),str(var2)],shell=True,stdin=PIPE,stderr=PIPE) print process.communicate() -------------------------------- shellscr.sh -------------------------------- #!/bin/bash echo $0 echo $1 echo $2 – creativeDrive Oct 11 '13 at 20:06
3

If you want to send arguments to shellscript from python script in a simple way.. You can use python os module :

import os  
os.system(' /path/shellscriptfile.sh {} {}' .format(str(var1), str(var2)) 

If you have more arguments.. Increase the flower braces and add the args.. In shellscript file.. This will read the arguments and u can execute the commands accordingly

WaLid LamRaoui
  • 2,305
  • 2
  • 15
  • 33