82

I wrote a script in python that takes a few files, runs a few tests and counts the number of total_bugs while writing new files with information for each (bugs+more).

To take a couple files from current working directory:

myscript.py -i input_name1 input_name2

When that job is done, I'd like the script to 'return total_bugs' but I'm not sure on the best way to implement this.

Currently, the script prints stuff like:

[working directory]
[files being opened]
[completed work for file a + num_of_bugs_for_a]
[completed work for file b + num_of_bugs_for_b]
...
[work complete]

A bit of help (notes/tips/code examples) could be helpful here.

Btw, this needs to work for windows and unix.

ofer.sheffer
  • 5,417
  • 7
  • 25
  • 26
  • 8
    It's generally a bad idea to try to use the return value of an executable to return anything but an error code or 0 for success. What are you going to do with this value when it's returned? – Wooble Aug 14 '13 at 12:13
  • 1
    Don't know about windows, but in linux it is common for programs to output the result to stdout. It seems like normally your script prints a bunch of information, but perhaps with a different flag (maybe c for count?), it just prints the total count of files, e.g. myscript.py -c -i input_name1 input_name2 – arghbleargh Aug 14 '13 at 12:18
  • @ Wooble, it is a script for finding bugs in report files. The value allows to estimate how well the report files are written. – ofer.sheffer Aug 14 '13 at 13:49
  • @arghbleargh, I decided to go with an extra bug report file but, pending on what my supervisor decides, I might change it to something like your suggestion. Thanks. – ofer.sheffer Aug 14 '13 at 13:51

1 Answers1

140

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:

Return values (from a wrapping-function)

(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)

Stdout as your relay

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 conveyors

There'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 conveyors

If 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.

Torxed
  • 22,866
  • 14
  • 82
  • 131
  • 2
    It's not from me, but I guess it's for suggesting os._exit() instead of sys.exit(). See http://docs.python.org/2/library/os.html#os._exit – rodion Aug 14 '13 at 12:16
  • Good point, i'm just used of writing `_exit()` so many times in my threaded applications that i thought it wasn't a big deal :S – Torxed Aug 14 '13 at 12:18
  • 4
    Or perhaps suggesting that exit codes be used to convey anything other than success or a handful of failure indications. – msw Aug 14 '13 at 12:18
  • 1
    You also can't `return` from a script, even if it's being imported. – Wooble Aug 14 '13 at 12:18
  • 2
    @Wooble ofc not, but the idea.. never mind, people are to perfectionistic to let me get away with pseudo code and general ideas about things. I'll be more specific -.- – Torxed Aug 14 '13 at 12:20
  • `os._exit()` is sometimes _very_ useful. I had a situation where `sys.exit()` triggered an infinite empty exception (maybe the process was trashed by something, well). – Jean-François Fabre Mar 29 '18 at 14:51
  • Wouldn't you usually use `def __main__():` to define the main function? – Stevoisiak Jun 02 '21 at 20:04
  • @Stevoisiak depends. History says `main()`, but you also do `if __name__ == "__main__":` to check the name of the source being executed, which contains `__main__` :) – Torxed Jun 03 '21 at 09:07