exit function not working - python

I am trying to exit the program if the value is not what I want but it doesn't do anything. What seems to be the problem? I think it stops the program but does not print "Invalid Subnet Mask".
from sys import exit
def maskvalidation(mask):
string = mask.split(".")
toInt = [int(i) for i in string]
binary = [bin(x) for x in toInt]
purebin = []
for x in binary:
purebin.append(x[2:])
if purebin[0] == "11111111":
print("good")
else:
exit("Invalid Subnet Mask")
maskvalidation("251.0.0.0")

help for sys.exit
exit(...)
exit([status])
Exit the interpreter by raising SystemExit(status).
If the status is omitted or None, it defaults to zero (i.e., success).
If the status is an integer, it will be used as the system exit status.
If it is another kind of object, it will be printed and the system
exit status will be one (i.e., failure).
So it is being used correctly in the question.
Furthermore, your sample program works fine for me on linux for Python2.7 and Python3.4.
It does however send the output to stderr rather than stdout, so perhaps that is the problem you are seeing

Related

Capture return value from python

I have a shell script TestNode.sh. This script has content like this:
port_up=$(python TestPorts.py)
python TestRPMs.py
Now, I want to capture the value returned by these scripts.
TestPorts.py
def CheckPorts():
if PortWorking(8080):
print "8080 working"
return "8080"
elif PortWorking(9090):
print "9090 working"
return "9090"
But as I checked the answers available, they are not working for me. The print is pushing the value in variable port_up, but I wanted that print should print on the console and the variable port_up should get the value from return statement. Is there a way to achieve this?
Note: I don't wish to use sys.exit(). Is it possible to achieve the same without this?
but I wanted that print should print on the console and the variable port_up should get the value from return statement.
Then don't capture the output. Instead do:
python TestPorts.py
port_up=$? # return value of the last statement
python TestRPMs.py
You could do:
def CheckPorts():
if PortWorking(8080):
sys.stderr.write("8080 working")
print 8080
But then I am not very happy to print "output" to stderr either.
Alternatively, you could skip printing that "8080 working" message in python script and print it from the shell script.
def CheckPorts():
if PortWorking(8080):
return "8080"
and:
port_up=$(python TestPorts.py)
echo "$port_up working"
python TestRPMs.py
To return an exit code from a Python script you can use sys.exit(); exit() may also work. In the Bash (and similar) shell, the exit code of the previous command can be found in $?.
However, the Linux shell exit codes are 8 bit unsigned integers, i.e. in the range 0-255, as mentioned in this answer. So your strategy isn't going to work.
Perhaps you can print "8080 working" to stderr or a logfile and print "8080" to stdout so you can capture it with $().

Python executables in /usr/bin directory are wrapped in sys.exit

Is there a difference between the two code snippets:
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
main()
Vs
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())
I see, most python executables in my ubuntu /usr/bin (or) /usr/local/bin directory use sys.exit. Doesn't the process stop, once the function returns.
Why do people wrap their executable functions inside sys.exit?
Note: This code is taken from openstack-nova python client and this question focusses only on python's sys.exit and not about openstack internals.
sys.exit() is there to pass the right exit code back to shell. If you want to differentiate the response in case of (for example) bad authentication, network issues, broken response, etc. exit codes are useful for that.
If you don't use specific sys.exit(value), you have two options only - success (exit code 0), or exception was thrown (exit code 1).
There are actually two ways to use sys.exit, as explained in the docs.
Your main can return 0 on success and 1 (or any other number from 2-127) on error; that number becomes your program's exit status. (The number 2 has a special meaning; it implies that the failure was because of invalid arguments. Some argument-parsing libraries will automatically sys.exit(2) if they can't parse the command line. The other numbers 3-127 all mean whatever you want them to.)
Or you can return None on success, and a string (or any object with a useful __str__ method) on failure. A None means exit status 0, anything else gets printed to stderr and gives exit status 1.
It used to be traditional to use the second form to signal failure by doing something like return "Failed to open file" from your main function, and the docs still mention doing that, but it's not very common anymore; it's just as easy, and more flexible, to output what you want and return the number you want.
If you just fall off the end of the script without a sys.exit, that's equivalent to sys.exit(0); if you exit through an exception, that's equivalent to passing the traceback to sys.exit—it prints the traceback to stderr and exits with status 1.

Return value from Python subprocess

I would like to get the output (print statements) and return status from a python subprocess along with displaying logging info. I am using Python 2.5 on Windows XP. How do I get the return code as well? Here in this extract, I am reading output so that I can redirect it to display in a wxPython TextCtrl in a separate thread.
self.myproc.poll()
if self.myproc.returncode is None:
# Still running so check stdout
txt = self.myproc.stdout.read(self._readblock)
if txt:
# Add to UI's update queue
self._parent.AppendUpdate(txt)
else:
break
The returncode gets returned by the poll call, and is also (once poll did not return None) accessible via the returncode attribute. You are already using this in your code, so I'm not sure what your problem with that is.
When you want to update your control while your process is running, use readline instead of read: the latter will wait for the entire output to be present, while the former will wait on a newline character. To give a full example using your variable names:
from subprocess import Popen, PIPE
self.myproc = Popen('dir /s', shell=True, stdout=PIPE, stderr=PIPE)
while self.myproc.poll() == None:
self._parent.AppendUpdate(self.myproc.stdout.readline())
self._parent.AppendUpdate('Return code was ' + self.myproc.returncode)
Note that you might want to .strip() the readline result as it will contain the newline character.
Edit: To address your confusion between the script output and its return code, the following. First, a Python script at module level cannot return a value: that would yield a syntax error. So what you should differentiate between is the output of the script, and the return code it gives.
The script's output is in the above example read by using the self.myproc.stdout.readline method. Every time the external process has produced a line of outputted text, calling that function would retrieve it.
The return code however (or exit status) is an integer that gets passed from a child process to the parent (your) process, indicating the state in which the child process exited. In Python, you do this with the sys.exit function. Most commonly, when this value is zero it indicates success; a non-zero value depicts some kind of error.
Say your child process script looks like this:
import sys
# Do some stuff
print 'pass' # Gets to stdout
sys.exit(0) # Return code
Executing this external file (let's call it test.py) with the Popen class, we will get pass when we read out self.myproc.stdout, and 0 when we read out self.myproc.poll (or self.myproc.returncode after the first poll).
The purpose of this return code is that you do not have to parse all of the child process' output to determine if it succeeded in its job: you are free to define your own exit codes. For example, you could consider 0 to be a success, 1 to be a failure, 2 to be some kind of invalid input given, 9 an unknown error, and so on. That way, you can just keep polling the process, and based on the exit code returned by that poll you directly know if it was successful. Note that this is a bit less applicable to your case as you need the output of the child process anyway, but still it is easier to parse a number than a string to determine success.

What is the return value of subprocess.call()?

I am not sure what the return value of subprocess.call() means.
Can I safely assume a zero value will always mean that the command executed successfully?
Is the return value equivalent to the exit staus of a shell command?
For example, will the following piece of code work for virtually any command on Linux?
cmd = "foo.txt > bar.txt"
ret = subprocess.call(cmd, shell=True)
if ret != 0:
if ret < 0:
print "Killed by signal", -ret
else:
print "Command failed with return code", ret
else:
print "SUCCESS!!"
Please enlighten me :-)
Yes, Subprocess.call returns "actual process return code".
You can check official documentation of Subprocess.call and Subprocess.Popen.returncode
It is the return code, but keep in mind it's up to the author of the subprocess what the return code means. There is a strong culture of 0 meaning success, but there's nothing enforcing it.
You are at the mercy of the commands that you call.
Consider this:
test.py
#!/usr/bin/env python
success=False
if not success:
exit()
Then running your code (with cmd='test.py') will result in
SUCCESS!!
merely because test.py does not conform to the convention of returning a non-zero value when it is not successful.

How to make the program run again after unexpected exit in Python?

I'm writing an IRC bot in Python, due to the alpha nature of it, it will likely get unexpected errors and exit.
What's the techniques that I can use to make the program run again?
You can use sys.exit() to tell that the program exited abnormally (generally, 1 is returned in case of error).
Your Python script could look something like this:
import sys
def main():
# ...
if __name__ == '__main__':
try:
main()
except Exception as e:
print >> sys.stderr, e
sys.exit(1)
else:
sys.exit()
You could call again main() in case of error, but the program might not be in a state where it can work correctly again.
It may be safer to launch the program in a new process instead.
So you could write a script which invokes the Python script, gets its return value when it finishes, and relaunches it if the return value is different from 0 (which is what sys.exit() uses as return value by default).
This may look something like this:
import subprocess
command = 'thescript'
args = ['arg1', 'arg2']
while True:
ret_code = subprocess.call([command] + args)
if ret_code == 0:
break
You can create wrapper using subprocess(http://docs.python.org/library/subprocess.html) which will spawn your application as a child process and track it's execution.
The easiest way is to catch errors, and close the old and open a new instance of the program when you do catch em.
Note that it will not always work (in cases it stops working without throwing an error).

Categories

Resources