If condition check with python - python

if not ping_device(ip):
if not reboot_device(device_1)
logger.error("Unable to reboot.. Serious issue")
break
logger.info("HARD Rebooted")
if not ping_device(ip):
logger.error("Ping failed after hard reboot")
else:
logger.info("Pinged success after reboot")
else:
logger.info("Pinged")
logger.info("Reboot passed")
logger.info("Getting uptime")
sw_version_check = get_sw_version(ip)
check_upgrade()
:
:
:
:
Here is my piece of code. Now if the ping_device fn in the first line succeeds, I have no problem. The else part comes into the picture.
Now if my first line ping_device fails, I call a reboot_device fn. after reboot, I again call the ping function to check my device is online.
After the ping success after the reboot, I need to get going with the else part of the first if condition with sw_version_check, check_upgrade() and rest of code traverses as mentioned with :
Will my logic after ping failure continue with sw_version_chec and check_upgrade?

You could have some separate variable, say doUpgrade, initialized to False and set to True at any point(s) in the first section where you have determined you need an upgrade. Then test that variable to see if the upgrade code needs to be executed.

Try using exceptions, they help make this type of control flow easier to reason about and are more "Pythonic":
def reboot_device(device):
if not your_reboot_device_fn(device):
raise DeviceRebootError('Unrecoverable reboot error')
else:
pass # Or anything else you want to do on success.
def ping_device(ip, device, did_try_reboot=False):
if not your_ping_device_fn(ip):
if did_try_reboot:
raise DevicePingError('Ping failed after hard reboot')
else:
try:
reboot_device(device)
except DeviceRebootError as e:
logging.error(e)
raise
else:
logger.info("HARD Rebooted")
ping_device(ip, device, did_try_reboot=True)
else:
pass # Or anything else you want to do on success.
try:
ping_device(ip, device_1)
except DevicePingError as e:
logging.error(e)
# NOTE: DeviceRebootError isn't caught so it will end the program.
else:
logging.info('Pinged')
sw_version_check = get_sw_version(ip)
check_upgrade()

Related

Python - While True: Try Except Else - Program Flow Question

I have this code using a While True with a try catch. The final else statement is always being executed when the 'try' is successful and I'd like to understand why - I think I'm not understanding the program flow correctly.
while True:
try:
subprocess.call(["wget", "-O", "splunk-8.0.1-6db836e2fb9e-Linux-x86_64.tgz", "https://www.splunk.com/bin/splunk/DownloadActivityServlet?architecture=x86_64&platform=linux&version=8.0.1&product=splunk&filename=splunk-8.0.1-6db836e2fb9e-Linux-x86_64.tgz&wget=true"])
print("successfully downloaded splunk enterprise")
time.sleep(2)
except OSError as e:
if e.errno == 2:
print(e)
print("wget doesn't seem to be installed")
time.sleep(2)
print("attempting to install wget")
time.sleep(2)
subprocess.call(["yum", "install", "wget"])
else:
print(e)
print("unknown error response, exiting...")
break
else:
print("something else went wrong while trying to download splunk")
break
based on python documentation, try-except can take an optional else statement:
The try … except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception.
so based on this, your else statement will run if codes in try doesn't raise any exception!
what you want is another except clause that catches a general exceptation, so you just need to replace else with except:
while True:
try:
subprocess.call(["wget", "-O", "splunk-8.0.1-6db836e2fb9e-Linux-x86_64.tgz", "https://www.splunk.com/bin/splunk/DownloadActivityServlet?architecture=x86_64&platform=linux&version=8.0.1&product=splunk&filename=splunk-8.0.1-6db836e2fb9e-Linux-x86_64.tgz&wget=true"])
print("successfully downloaded splunk enterprise")
time.sleep(2)
except OSError as e:
if e.errno == 2:
print(e)
print("wget doesn't seem to be installed")
time.sleep(2)
print("attempting to install wget")
time.sleep(2)
subprocess.call(["yum", "install", "wget"])
else:
print(e)
print("unknown error response, exiting...")
break
except:
print("something else went wrong while trying to download splunk")
break
The else clause of a try executes if the code inside the try did not throw an exception. If you want to catch any exception, use except without specifying an exception class:
except:
print("something else went wrong while trying to download splunk")
break
However, consider just omitting this piece of code. As it is currently written, it doesn't tell you what went wrong. If you remove these lines, you will get an error message that tells you what happened and on which line the error occurred.
From here:
The try … except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception.
So the else clause will run if the code within the try block runs successfully.

How to clear the exception state in Python

I have a try/except block around a call to an API. It appears to me that once I get an exception, all valid try cases after that exception will see the same exception. The only way I have been able to get it to work is to re-start my Python script. I googled around and found PyErr_clear() but that is for the C-API. Is there something I can call from plain-old Python that will clear the exception state?
Here is the basic idea of what I am doing:
def get_and_print_data(key):
try:
data = get_data_from_some_3rd_party_api(key)
except Exception as ex:
print("Failed to get data for",key,": ",str(ex))
return
print("data=",data)
Then in main I have
get_and_print_data("Valid Key") ## This works
get_and_print_data("INvalid Key") ## This gets exception, as expected
get_and_print_data("Valid Key") ## This and all subsequent calls to get_and_print_data() fail with the same exception.
As an example of why I think it's the 3rd party API that is having issues:
def get_data_from_some_3rd_party_api(key):
if key == "Valid Key":
return "This is some good data."
else:
raise ValueError("Invalid Key")
def get_and_print_data(key):
try:
data = get_data_from_some_3rd_party_api(key)
except Exception as ex:
print("Failed to get data for",key,": ",str(ex))
return
print("data=",data)
get_and_print_data("Valid Key") ## This works
get_and_print_data("INvalid Key") ## This gets exception, as expected
get_and_print_data("Valid Key") ## This works
Try running this locally, and you should see that the subsequent valid keys still work.

How to skip the Index

#main program
while True:
ReadValue = Func03Modbus(1,70,40);#slave,start,number of registers
x3 = struct.pack('>HH',abs(ReadValue[3]),abs(ReadValue[2]))
pressure = struct.unpack('>f', x3)
print pressure[0]
c3 = struct.pack('>HH',abs(ReadValue[5]),abs(ReadValue[4]))
purity = struct.unpack('>f', c3)
print purity[0]
hrs = int(ReadValue[30])
mins= int(ReadValue[31])
timein =float(str(ReadValue[30])+"."+str(ReadValue[31]))
print timein
r=requests.get("http://api.thingspeak.com/update api_key=5RMT************&field4="+str(pressure[0])+"&field5="+str(purity[0])+"&field1="+str(ReadValue[i])+"&field2="+str(mins)+"&field3="+str(timein)))
print str(ReadValue[30])
time.sleep(15)
While running the above program it stops running with returning following error:
Traceback (most recent call last): File "/home/pi/v1.py", line 123,
in
x3 = struct.pack('>HH',abs(ReadValue[3]),abs(ReadValue[2])); IndexError: tuple index out of range
I want my program to run continuously even when it returns error. I want to skip the error and to run the program continuously. How can I do that ?
In theory you could wrap the code in an exception handler like:
while True:
try:
what you want to do
except Exception as e:
print("Something bad happened:", e)
finally:
# reset device here
time.sleep(15)
But this seems like a really bad idea if you're interacting with hardware, since you can't be sure what state you're leaving it in. Ideally, you'd want to make sure you're doing a proper reset of the device (or reconnect? depends what you're talking to) on every cycle.
Alternatively, if you want to explicitly verify that the values you get back are available, you can do:
ReadValue = Func03Modbus(1,70,40);#slave,start,number of registers
if len(ReadValue) < 32:
print("Got incomplete result")
time.sleep(15)
continue
The language reference/tutorial has more information about handling errors here: https://docs.python.org/3/tutorial/errors.html
In order to continue in the event of this kind of error, simply place the part you wish to ignore exceptions in within an appropriate try: ... except ...
while True:
try:
<body of work>
except IndexError:
<you might want to log the error>
pass
In this case, we continue only in the event of IndexError.

can i combine if else and with try catch python?

i have a code :
s = '127.0.0.0'
def validate(a):
a = s.split('.')
if len(a) !=4:
return False
for x in a :
if not x.isdigit():
return False
i = int(x)
if i < 0 or i > 255 :
return False
return False
try:
validate(s) #ip validation
#my code here
except :
print("insert you're ip correctly")
can i combine if else with try catch like that?
if the try catch got error message or like return false from if condition it will run the except condition, if not it will run the try condition until the process is end.
there's have a better ways to dot this?
You can raise an exception if the function returns False, by doing:
s = '127.0.0.0'
def validate(a):
a = a.split('.')
if len(a) !=4:
return False
for x in a :
if not x.isdigit():
return False
i = int(x)
if i < 0 or i > 255 :
return False
return True
try:
if not validate(s): #ip validation
raise TypeError
except TypeError:
print("insert you're ip correctly")
Note: you probably want to return True for the end, since I believe that's when the function validates successfully, and a = a.split('.') not s.split, or else you're splitting the global variable s.
Tip: when using try...except, try to catch a specific error than to use the catch-all except:.
The answers above may be technically correct, but considering coding style etc. I don't see any reason to use exceptions here instead a plain if else:
if not validate(s): #ip validation
print("insert you're ip correctly")
That actually does what you want and it's much cleaner and better to read.
Try/catch is to handle exceptions, not to handle return values from methods. In your case, what you wrote would compile but is not what you want to do.
The easiest solution for you would be it use what already exists in python, ie. socket, which can nicely validate IP for you. If you still want to use the validate() method for other purpose, then you can write:
import socket
def validate(a):
socket.inet_aton(s)
try:
validate(s)
# your code here
except socket.error:
print("insert your ip correctly")
In that case, the socket.inet_aton method will raise the exception socket.error, which you can then catch. If for some reason you do not want to use socket, then you can define your own exception, raise it from validate() and catch it outside validate().
For Python 3, you will be better served by ipaddress as socket is too permissive (for good reasons, see man inet(3)):
import ipaddress
def validate(a):
ipaddress.ip_address(a)
try:
validate(s)
# your code here
except ValueError:
print("insert your ip correctly")
On a side note, I believe you want to return True as the last line of validate(), but that would not change the problem.
On a (second) side note, catching all exceptions (bare catch statement) is bad practice. In your code you handle a specific error (IP not valid) you should only catch exceptions related to this problem.

How do I exit program in try/except?

I have this try/except code:
document = raw_input ('Your document name is ')
try:
with open(document, 'r') as a:
for element in a:
print element
except:
print document, 'does not exist'
How do I exit the program after I print "[filename] does not exist"? break and pass obviously don't work, and I don't want to have any crashing errors, so sys.exit is not an option.
Please ignore the try part - it's just a dummy.
Use the sys.exit:
import sys
try:
# do something
except Exception, e:
print >> sys.stderr, "does not exist"
print >> sys.stderr, "Exception: %s" % str(e)
sys.exit(1)
A good practice is to print the Exception that occured so you can debug afterwards.
You can also print the stacktrace with the traceback module.
Note that the int you return in sys.exit will be the return code of your program. To see what exit code your program returned (which will give you information about what happens and can be automated), you can do:
echo $?
Using
sys.exit(1)
is not a crashing error, it's a perfectly normal way to exit a program. The exit code of 1 is a convention that means something went wrong (you would return 0 in the case of a successful run).
Just re-raise it. It's more friendly for developer
document = raw_input ('Your document name is ')
try:
with open(document, 'r') as a:
for element in a:
print element
except:
print document, 'does not exist'
raise
Check python document in the Raising Exceptions section about re-raise error in except.
You can also put your code in a function and issue a return. You may call it main which you can call from your script.
def main():
document = raw_input ('Your document name is ')
try:
with open(document, 'r') as a:
for element in a:
print element
except:
print document, 'does not exist'
return
if __name__ == "__main__":
main()
In case that you are using an if statement inside a try, you are going to need more than one sys.exit() to actually exit the program.
For example, you are parsing an argument when calling the execution of some file, e.g. $./do_instructions.py 821 such as:
import sys
# index number 1 is used to pass a set of instructions to parse
# allowed values are integer numbers from 1 to 4, maximum number of instructions is 3
arg_vector = "821" # <- pretending to be an example of sys.argv[1]
if len(arg_vector) > 3:
sys.exit(2) # <- this will take you out, but the following needs an extra step.
# for an invalid input (8).
for i in arg_vector:
# to validate that only numbers are passed as args.
try:
int(i) # <- 8 is valid so far
# value (8) is not valid, since is greater than 4
if (int(i) == 0) or (int(i) > 4):
print("Values must be 1-4")
# the following call does not takes you out from the program,
# but rise the SystemExit exception.
sys.exit(2)
except SystemExit: # <- needed to catch the previous as the first evaluation
# The following parameter "2" is just for this example
sys.exit(2) # <- needed to actually interrupt the execution of the program/script.
# if there is no "except SystemExit:", the following will be executed when the
# previous "if" statement evaluates to True and the sys.exit(2) is called.
#
# and the "print("Only num...") function will be called, even when the intention
# of it is to advice the *user* to use only numbers, since 8 is a number this
# shouldn't be executed.
except:
print("Only numbers are allowed.")
sys.exit(2)
otherwise, you want to use one try-except block for each evaluation.
Probably not the best practice, but it worked for me:
import sys
close = False
try:
if SomethingBadHappend:
close = True
except:
pass
if close:
sys.exit(1)
Close dose does not seem to work inside 'try'.

Categories