return value from python script to shell script
You can't return message as exit code, only numbers. In bash it can accessible via $?
. Also you can use sys.argv
to access code parameters:
import sys
if sys.argv[1]=='hi':
print 'Salaam'
sys.exit(0)
in shell:
#!/bin/bash
# script for tesing
clear
echo "............script started............"
sleep 1
result=`python python/pythonScript1.py "hi"`
if [ "$result" == "Salaam" ]; then
echo "script return correct response"
fi
Assign return value from python method to a variable in bash script
When you run this:
password_check=$(python password.py $password)
You are assigning the output of the password.py
program to the password_check
variable. The problem is that your password.py
program doesn't produce any output: in fact, it never even runs the passwordCheck
function, because your Python script never calls passwordCheck
. Do make things work the way you're trying to use the script, you would need to modify it to (a) actually call the passwordCheck
method and (b) print output instead of return
ing a value:
import re, sys
password = sys.argv[1]
def passwordCheck():
if re.match(r'(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z])(?=.*[^A-Za-z0-9]).{14,}', password):
print 'okay'
return True
else:
print 'fail'
return False
passwordCheck()
And then check for that value in your shell script:
#!bin/sh
password="Testing@2134testing"
password_check=$(python password.py $password)
if [ "$password_check" == "okay" ];then
echo "Correct"
else
echo "Incorrect"
fi
Note that Python doesn't require a terminal ;
on lines, so instead
of:
return False;
You should write:
return False
Additionally, in this example we're using the output of the script
to determine success/failure. A slightly more robust solution is to
use the exit code of the script instead. You can probably find a
variety of examples of using this technique if you explore online a
bit.
Grab return value from python with Shell Script
The
outputString=$(python swdl_number_receiver.py)
construction captures text sent to stdout
. If you want your script to print information to the terminal then you can send it to stderr
. Here's a simple demo.
qtest.py
import sys
print >>sys.stderr, "this is sent to stderr"
print "this is sent to stdout"
In Bash:
$ outputString=$(python qtest.py);echo "ok";echo "$outputString"
output
this is sent to stderr
ok
this is sent to stdout
Here's a version of qtest.py that works on Python 2 and Python 3:
from __future__ import print_function
import sys
print("this is sent to stderr", file=sys.stderr)
print("this is sent to stdout")
If you also want to capture the output sent to stderr
in a variable, one way to do that, without changing "qtest.py", is to redirect stderr
in Bash to a file:
$ outputString=$(python qtest.py 2>qtemp);echo "ok";stderrString=$(<qtemp);echo "STDOUT: $outputString";echo "STDERR: $stderrString"
ok
STDOUT: this is sent to stdout
STDERR: this is sent to stderr
A better way is to write directly to the file in Python:
qtest.py
from __future__ import print_function
with open("qtemp", "w") as f:
print("this is sent to qtemp", file=f)
print("this is sent to stdout")
bash
$ outputString=$(python qtest.py);echo "ok";qtempString=$(<qtemp);echo "STDOUT: $outputString";echo "qtemp: $qtempString"
ok
STDOUT: this is sent to stdout
qtemp: this is sent to qtemp
store return value of a Python script in a bash script
sys.exit(myString)
doesn't mean "return this string". If you pass a string to sys.exit
, sys.exit
will consider that string to be an error message, and it will write that string to stderr
. The closest concept to a return value for an entire program is its exit status, which must be an integer.
If you want to capture output written to stderr, you can do something like
python yourscript 2> return_file
You could do something like that in your bash script
output=$((your command here) 2> &1)
This is not guaranteed to capture only the value passed to sys.exit
, though. Anything else written to stderr will also be captured, which might include logging output or stack traces.
example:
test.py
print "something"
exit('ohoh')
t.sh
va=$(python test.py 2>&1)
mkdir $va
bash t.sh
edit
Not sure why but in that case, I would write a main script and two other scripts... Mixing python and bash is pointless unless you really need to.
import script1
import script2
if __name__ == '__main__':
filename = script1.run(sys.args)
script2.run(filename)
How to access python return value from bash script
Add a proper exit code from your script using the sys.exit()
module. Usually commands return 0 on successful completion of a script.
import sys
def main():
print ("exec main..")
sys.exit(0)
and capture it in shell script with a simple conditional. Though the exit code is 0 by default and need not be passed explicitly, using sys.exit()
gives control to return non-zero codes on error cases wherever applicable to understand some inconsistencies with the script.
if python foo.py 2>&1 >/dev/null; then
echo 'script ran fine'
fi
Capture return value from python script in command line
If the return value (which is unclear in the question) is a single line of output you could simply:
./script.py | tail -n 1
This will output the last line generated from the script (adjust the number as needed).
If you want to save to a file either >
to create a new file, or >>
to append to a file:
./script.py | tail -n 1 > file
Best way to return a value from a python script
If you want your script to return values, just do return [1,2,3]
from a function wrapping your code but then you'd have to import your script from another script to even have any use for that information:
(again, this would have to be run by a separate Python script and be imported in order to even do any good):
import ...
def main():
# calculate stuff
return [1,2,3]
Exit codes as indicators(This is generally just good for when you want to indicate to a governor what went wrong or simply the number of bugs/rows counted or w/e. Normally 0 is a good exit and >=1 is a bad exit but you could inter-prate them in any way you want to get data out of it)
import sys
# calculate and stuff
sys.exit(100)
And exit with a specific exit code depending on what you want that to tell your governor.
I used exit codes when running script by a scheduling and monitoring environment to indicate what has happened.
(os._exit(100)
also works, and is a bit more forceful)
If not you'd have to use stdout to communicate with the outside world (like you've described).
But that's generally a bad idea unless it's a parser executing your script and can catch whatever it is you're reporting to.
import sys
# calculate stuff
sys.stdout.write('Bugs: 5|Other: 10\n')
sys.stdout.flush()
sys.exit(0)
Are you running your script in a controlled scheduling environment then exit codes are the best way to go.
Files as conveyorsThere's also the option to simply write information to a file, and store the result there.
# calculate
with open('finish.txt', 'wb') as fh:
fh.write(str(5)+'\n')
And pick up the value/result from there. You could even do it in a CSV format for others to read simplistically.
Sockets as conveyorsIf none of the above work, you can also use network sockets locally *(unix sockets is a great way on nix systems). These are a bit more intricate and deserve their own post/answer. But editing to add it here as it's a good option to communicate between processes. Especially if they should run multiple tasks and return values.
Running shell command and capturing the output
In all officially maintained versions of Python, the simplest approach is to use the subprocess.check_output
function:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
runs a single program that takes only arguments as input.1 It returns the result exactly as printed to stdout
. If you need to write input to stdin
, skip ahead to the run
or Popen
sections. If you want to execute complex shell commands, see the note on shell=True
at the end of this answer.
The check_output
function works in all officially maintained versions of Python. But for more recent versions, a more flexible approach is available.
Modern versions of Python (3.5 or higher): run
If you're using Python 3.5+, and do not need backwards compatibility, the new run
function is recommended by the official documentation for most tasks. It provides a very general, high-level API for the subprocess
module. To capture the output of a program, pass the subprocess.PIPE
flag to the stdout
keyword argument. Then access the stdout
attribute of the returned CompletedProcess
object:
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
The return value is a bytes
object, so if you want a proper string, you'll need to decode
it. Assuming the called process returns a UTF-8-encoded string:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
This can all be compressed to a one-liner if desired:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
If you want to pass input to the process's stdin
, you can pass a bytes
object to the input
keyword argument:
>>> cmd = ['awk', 'length($0) > 5']
>>> ip = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=ip)
>>> result.stdout.decode('utf-8')
'foofoo\n'
You can capture errors by passing stderr=subprocess.PIPE
(capture to result.stderr
) or stderr=subprocess.STDOUT
(capture to result.stdout
along with regular output). If you want run
to throw an exception when the process returns a nonzero exit code, you can pass check=True
. (Or you can check the returncode
attribute of result
above.) When security is not a concern, you can also run more complex shell commands by passing shell=True
as described at the end of this answer.
Later versions of Python streamline the above further. In Python 3.7+, the above one-liner can be spelled like this:
>>> subprocess.run(['ls', '-l'], capture_output=True, text=True).stdout
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Using run
this way adds just a bit of complexity, compared to the old way of doing things. But now you can do almost anything you need to do with the run
function alone.
Older versions of Python (3-3.4): more about check_output
If you are using an older version of Python, or need modest backwards compatibility, you can use the check_output
function as briefly described above. It has been available since Python 2.7.
subprocess.check_output(*popenargs, **kwargs)
It takes takes the same arguments as Popen
(see below), and returns a string containing the program's output. The beginning of this answer has a more detailed usage example. In Python 3.5+, check_output
is equivalent to executing run
with check=True
and stdout=PIPE
, and returning just the stdout
attribute.
You can pass stderr=subprocess.STDOUT
to ensure that error messages are included in the returned output. When security is not a concern, you can also run more complex shell commands by passing shell=True
as described at the end of this answer.
If you need to pipe from stderr
or pass input to the process, check_output
won't be up to the task. See the Popen
examples below in that case.
Complex applications and legacy versions of Python (2.6 and below): Popen
If you need deep backwards compatibility, or if you need more sophisticated functionality than check_output
or run
provide, you'll have to work directly with Popen
objects, which encapsulate the low-level API for subprocesses.
The Popen
constructor accepts either a single command without arguments, or a list containing a command as its first item, followed by any number of arguments, each as a separate item in the list. shlex.split
can help parse strings into appropriately formatted lists. Popen
objects also accept a host of different arguments for process IO management and low-level configuration.
To send input and capture output, communicate
is almost always the preferred method. As in:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
Or
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
If you set stdin=PIPE
, communicate
also allows you to pass data to the process via stdin
:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Note Aaron Hall's answer, which indicates that on some systems, you may need to set stdout
, stderr
, and stdin
all to PIPE
(or DEVNULL
) to get communicate
to work at all.
In some rare cases, you may need complex, real-time output capturing. Vartec's answer suggests a way forward, but methods other than communicate
are prone to deadlocks if not used carefully.
As with all the above functions, when security is not a concern, you can run more complex shell commands by passing shell=True
.
Notes
1. Running shell commands: the shell=True
argument
Normally, each call to run
, check_output
, or the Popen
constructor executes a single program. That means no fancy bash-style pipes. If you want to run complex shell commands, you can pass shell=True
, which all three functions support. For example:
>>> subprocess.check_output('cat books/* | wc', shell=True, text=True)
' 1299377 17005208 101299376\n'
However, doing this raises security concerns. If you're doing anything more than light scripting, you might be better off calling each process separately, and passing the output from each as an input to the next, via
run(cmd, [stdout=etc...], input=other_output)
Or
Popen(cmd, [stdout=etc...]).communicate(other_output)
The temptation to directly connect pipes is strong; resist it. Otherwise, you'll likely see deadlocks or have to do hacky things like this.
Related Topics
Replace Single Quote With Double Quote in a String Python
Get the Row(S) Which Have the Max Value in Groups Using Groupby
How to Save All the Variables in the Current Python Session
Selecting Specific Rows and Columns from Numpy Array
Print() Prints Only Every Second Input
How to Index a Middle Character in a List in Python
Python Xlsxwriter Set Border Around Multiple Cells
Python Selenium, Find Out When a Download Has Completed
Get List of Files in a Sharepoint Directory Using Python
Python Db-Api: Fetchone VS Fetchmany VS Fetchall
How to Check All Versions of Python Installed on Osx and Centos
Convert Number Strings With Commas in Pandas Dataframe to Float
Finding the Max Value in a Two Dimensional Array
Find the Index of a Value in a 2D Array