I have a problem with the following code:
callBash.py:
import subprocess
print "start"
subprocess.call("sleep.sh")
print "end"
sleep.sh:
sleep 10
I want the "end" to be printed after 10s. (I know that this is a dumb example, I could simply sleep within python, but this simple sleep.sh file was just as a test)
-
I also tried it with "$!bin/bash; sleep 10; "user1638145– user16381452012年12月06日 14:29:20 +00:00Commented Dec 6, 2012 at 14:29
-
2It is unclear what problem this questien is trying to ask about, but the question should probably remain because it has accrued a historical grab bag of more or less good guesses as answers. Probably also search for your specific error, and/or read related questions like stackoverflow.com/questions/4256107/…tripleee– tripleee2020年06月02日 02:08:48 +00:00Commented Jun 2, 2020 at 2:08
7 Answers 7
Making sleep.sh executable and adding shell=True to the parameter list (as suggested in previous answers) works ok. Depending on the search path, you may also need to add ./ or some other appropriate path. (Ie, change "sleep.sh" to "./sleep.sh".)
The shell=True parameter is not needed (under a Posix system like Linux) if the first line of the bash script is a path to a shell; for example, #!/bin/bash.
1 Comment
shell=True is discouraged - docs because it makes your program vulnerable to shell injectionsIf sleep.sh has the shebang #!/bin/sh and it has appropriate file permissions -- run chmod u+rx sleep.sh to make sure and it is in $PATH then your code should work as is:
import subprocess
rc = subprocess.call("sleep.sh")
If the script is not in the PATH then specify the full path to it e.g., if it is in the current working directory:
from subprocess import call
rc = call("./sleep.sh")
If the script has no shebang then you need to specify shell=True:
rc = call("./sleep.sh", shell=True)
If the script has no executable permissions and you can't change it e.g., by running os.chmod('sleep.sh', 0o755) then you could read the script as a text file and pass the string to subprocess module instead:
with open('sleep.sh', 'rb') as file:
script = file.read()
rc = call(script, shell=True)
3 Comments
import I want to use your code for homework and we cant use import in the py filesubprocess module. There are ways to do it without the explicit import in Python but those are dirty hacks reserved for escaping from a sandboxed environment (it is unlikely to be your homework unless you are learning about security in Python).shell=True and in fact using #!/usr/bin/env zsh instead since this was macos w zsh.If someone looking for calling a script with arguments
import subprocess
val = subprocess.check_call("./script.sh '%s'" % arg, shell=True)
Remember to convert the args to string before passing, using str(arg).
This can be used to pass as many arguments as desired:
subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)
1 Comment
subprocess.check_call(["./script.ksh", arg1, arg2, arg3], shell=True) which seems clearer to me and you do not need to care about formatting.Actually, you just have to add the shell=True argument:
subprocess.call("sleep.sh", shell=True)
But beware -
Warning Invoking the system shell with shell=True can be a security hazard if combined with untrusted input. See the warning under Frequently Used Arguments for details.
Make sure that sleep.sh has execution permissions, and run it with shell=True:
#!/usr/bin/python
import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"
2 Comments
#!bin/bash is a missing /. #!/bin/bash works as I note in an answer.If chmod is not working then you can also try:
import os
os.system('sh script.sh')
# you can also use bash instead of sh
1 Comment
os.system documentation specifically recommends avoiding it in favor of subprocess (these days, subprocess.run()). If you can't get subprocess to work, chances are you'll have trouble with os.system() too.Adding an answer because I was directed here after asking how to run a bash script from python. You receive an error OSError: [Errno 2] file not found if your script takes in parameters. Lets say for instance your script took in a sleep time parameter: subprocess.call("sleep.sh 10") will not work, you must pass it as an array: subprocess.call(["sleep.sh", 10])
1 Comment
shell=True but yes, usually avoiding it is your best play.