Nepal12 Nepal12 - 7 days ago 5
Bash Question

Grab return value from python with Shell Script

I am aware that a similar kind of question has already been asked and answered.
However, my question deals with a slightly different type of problem and implementation:

The situation is:

I need to build a shell script which will capture the return value of a python (2.7) script, which will then be used in a jenkins job.
In the python script, I have to read an SVN checkout text file and return the value of the file, update the value of the file, and commit it.

I have implemented the following code:

swdl_number_receiver.py

import posixpath
import os
import sys
import subprocess

SVN_VERSION_DIR_PATH = 'data'
SWDL_FILE_NAME = "swdl_number.txt"

# Exit codes
class ExitCode:
""" Exit code Enumeration """
SUCCESS = 0
FAILURE = 1

# get SWDL number from the file
def getSWDLNumber():
work_dir = posixpath.join(os.getcwd(),SVN_VERSION_DIR_PATH)
version_number = None
new_version_number = None

# Read the File
os.chdir(work_dir)
with open(SWDL_FILE_NAME, "r") as input_file:
for line in input_file:
version_number = str.strip(line)
if version_number is None:
print "---- SWDL NUmber is empty existing the code ....... "
sys.exit(ExitCode.FAILURE)
else:
print "++++ The found SWDL number is : " + version_number
new_version_number = int(version_number) + 1
print "++++ The New SWDL Number is : " + str(new_version_number)

print "++++ Writing the new SWDL Number from " + str(version_number) + " to " + str(new_version_number)
#replace the file with new content
os.remove(SWDL_FILE_NAME)
with open(SWDL_FILE_NAME, 'wb') as output:
output.write(str(new_version_number).rstrip('\n'))

checkin_message = '"Updated SWDL Number to : ' + str(new_version_number) + '"'
try:
subprocess.call(['svn', 'commit', '-m ' + checkin_message, SWDL_FILE_NAME, '--non-interactive'])
except:
sys.exit(ExitCode.FAILURE)

return new_version_number


if __name__ == "__main__":
print getSWDLNumber()


In my shell script I am doing:

outputString=$(python swdl_number_receiver.py)
echo $outputString


The swdl_number.txt contains only one line with 5 digits.

My problem:
When I comment out all the "print" lines and the try and catch for the SVN commit, I get only new_version_number as the return value.
In other words, If I uncomment all the lines with print statements and the try and catch block for SVN commit, then on the shell script as $output_string I get every print statements and the commit message as well as the "new_version_number". And If I comment out all the print statement and try and catch block then I am getting the desired "new_version_number".

How should my code be modified in order to get the only required "new_version_number" return, and display all print lines?

Answer

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