9

I'm trying to write a python script that returns a value which I can then pass in to a bash script. Thing is that I want a singe value returned in bash, but I want a few things printed to the terminal along the way.

Here is an example script. Let's call it return5.py:

#! /usr/bin/env python
print "hi"
sys.stdout.write(str(5))

what I want is to have this perform this way when I run it from the command line:

~:five=`./return5.py`
hi
~:echo $five
5

but what I get is:

~:five=`./return5.py`
~:echo $five
hi 5

In other words I don't know how to have a python script print and clear the stdout, then assign it to the specific value I want.

nobody
  • 19,814
  • 17
  • 56
  • 77
arwright3
  • 381
  • 2
  • 3
  • 13
  • I'm confused -- what do you think the terminal IS, if not stdout? If you just need them on separate lines that's possible using `import sys; sys.stdout.flush()` – Adam Smith Apr 16 '14 at 19:21
  • is what you are going to be returing to the shell always going to be a number? you can use `sys.exit(5)` and the look at `$?` but this is also non standard behavior – Doon Apr 16 '14 at 19:33
  • Numeric exit codes are not "non standard behavior" in any sense - it is a very well established concept. Some environments may restrict the range, though (such as 0-127). – nobody Apr 16 '14 at 19:42
  • @AndrewMedico, it's non-standard because there is a strong convention to have 0 represent "everything's good" and non-zero represent an error case. – bgschiller Apr 16 '14 at 19:47
  • yes i was going for non-standard as in 0 is all well, and anything else == oops – Doon Apr 16 '14 at 19:50
  • @AdamSmith when I say **terminal** I mean what's printed on my terminal screen. when I say **stdout** I mean the thing that is assigned to x when I type ```x=`command` ``` – arwright3 Apr 16 '14 at 20:07
  • As an aside, you should use quotes: `echo "$five"` – tripleee Apr 17 '14 at 05:44

3 Answers3

10

Not sure why @yorodm suggests not to use stderr. That's the best option I can think of in this case.

Notice that print will add a newline automatically, but when you use sys.stderr.write, you need to include one yourself with a "\n".

#! /usr/bin/env python
import sys


sys.stderr.write("This is an important message,")
sys.stderr.write(" but I dont want it to be considered")
sys.stderr.write(" part of the output. \n")
sys.stderr.write("It will be printed to the screen.\n")

# The following will be output.
print 5

Using this script looks like this:

bash$ five=`./return5.py`
This is an important message, but I dont want it to be considered part of the output.
It will be printed to the screen.
bash$ echo $five
5

This works because the terminal is really showing you three streams of information : stdout, stdin and stderr. The `cmd` syntax says "capture the stdout from this process", but it doesn't affect what happens to stderr. This was designed exactly for the purpose you're using it for -- communicating information about errors, warnings or what's going on inside the process.

You may not have realized that stdin is also displayed in the terminal, because it's just what shows up when you type. But it wouldn't have to be that way. You could imagine typing into the terminal and having nothing show up. In fact, this is exactly what happens when you type in a password. You're still sending data to stdin, but the terminal is not displaying it.

bgschiller
  • 2,087
  • 1
  • 16
  • 30
2

from my comment..

#!/usr/bin/env python
#foo.py 

import sys
print "hi"
sys.exit(5)

then the output

[~] ./foo.py
hi
[~] FIVE=$?
[~] echo $FIVE
5
Doon
  • 19,719
  • 3
  • 40
  • 44
0

You can use stdout to output your messages and stderr to capture the values in bash. Unfortunately this is some weird behaviour as stderr is intended for programs to communicate error messages so I strongly advice you against it.

OTOH you can always process your script output in bash

yorodm
  • 4,359
  • 24
  • 32