0

I have a python script a.py which is run by a shell script b.sh. I wish to return the result (which is int) of a.py to b.sh.

I know I can use sys.exit(result) in a.py. But as I wrote set -ex in b.sh, the shell script stops after running a.py. I don't wish to use print(result) eather because I wish to print other information in a.py.

Is there any other way to return result from a.py to b.sh?

6
  • you could print to another stream than STDOUT and b could read from it Commented Dec 7, 2021 at 6:51
  • @ThorstenStaerk How to print to another stream and how can b read from it? Commented Dec 7, 2021 at 6:54
  • dev.to/0xbf/use-mkfifo-to-create-named-pipe-linux-tips-5bbk Commented Dec 7, 2021 at 7:00
  • Don't use set -e. Commented Dec 7, 2021 at 7:07
  • You can of course invoke your script as a.py||false, but what's the point in returning a certain exit code, if you don't want to evaluate it? Commented Dec 7, 2021 at 7:14

4 Answers 4

1

I agree with chepner, that the exit codes should not be used for integer passing. Why not passing output of the python-file via stdout?

value="$(python foo.py)"
echo "${value}"
Sign up to request clarification or add additional context in comments.

Comments

1

I would recommend writing the integer value to a file. I completely agree that exit codes should not be used for passing any information, other than success or failure of the program.

For example b.sh:

#! /bin/bash
set -ex

# Create temp file, ensure it is erased on bash script exit
tempfile="$(mktemp)"
trap 'rm -f "$tempfile"' EXIT
trap 'exit 1' HUP INT QUIT PIPE TERM

# Run program and write value to temp file
python3 ./a.py -o "$tempfile"

# Read value from temp file
myvalue="$(cat "$tempfile")"

echo "Value from a.py was: $myvalue"

And a.py:

#! /usr/bin/env python3

import argparse
from pathlib import Path

parser = argparse.ArgumentParser()
parser.add_argument(
    "-o",
    "--output-file",
    help="Write integer value to text file",
    type=str,
    required=True,
)
args = parser.parse_args()

my_value = 42
Path(args.output_file).write_text(str(my_value))

Comments

0

You can do something like this:

{ a.py; result=$?; } || true
# the result of a.py is in $result

|| true temporarily disables set -e, and the $? special variable gets stored to $result before it gets overwritten by the next command.

The downside is that, if your script actually fails (e.g. by raising an exception), you won't notice that. A more robust solution would be to print the needed result and catch it as output, and print the other output to the standard error.

Comments

0

You can return the exit code from the python script and look it up (and reassign to another variable if necessary) in the shell script via $?:

foo.py:

import sys
sys.exit(35)

foo.sh:

python foo.py
echo $?

Run the scripts:

> sh foo.sh
35

3 Comments

Please note the OP sets set -ex in the shell script.
Don't abuse exit codes for passing integer data.
@chapter Why do you call it abuse?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.