raising an error in try/except/finally model code - python

I'm writing a code that uses files.
I want to check if the name of the files are empty string, and if so to raise a ValueError. Moreover, I want to close all the files, no matter what
Can I raise a ValueError before the "try" block of the code?
Is it OK to write the code only with "try" and "finally"?
`def functio(file_1, file_2):
if file_1 == '' or file_2 == '':
raise ValueError("Invalid input")
try:
~rest of the code~
finally:
if file_1 =! None or file_2 != None:
file_1.close()
file_2.close()`

Python has something called 'context managers' which help you with what you're trying to do.
def function(file_1, file_2):
if file_1 == '' or file_2 == '':
raise ValueError("Invalid input")
with open(file_1) as f1, open(file_2) as f2:
... # here goes the code that handles the files
Files will be opened at the start of the with block and will be closed appropriately when exiting the block.
Can I raise a ValueError before the "try" block of the code?
Yes, you can. However, it will abort the execution of the program if there's no except block to catch it.
Is it OK to write the code only with "try" and "finally"?
Yes, you can. But it's more correct to use context managers for this, as I described above.

You can, but the exception will be raised and the code will stop.
You can do that, but if there is an error in the try portion, the code will stop if you don't have a except:. However it will execute the finally: part before stopping.

Related

How to Catch Exception in for loop and return exception only after loop is done?

Hi I have a function that parses the first 60 lines in a file and is supposed to alert a user if there are lines that are entirely whitespace. However these can occur anywhere in those 60 lines so I want the script to parse the entire 60 lines mainly because I need data from a couple of the lines for my error reporting. And we might want to know where those errors occur in the future. I wrote this:
def header_data(data):
dictionary = {}
datalen = len(data)
itrcntr = 0
try:
for line in data:
itrcntr += 1
if line.isspace():
raise Exception('File has badly formatted header data line(s)')
else:
linesplit = line.rstrip().split(":")
if len(linesplit) > 1:
dictionary[linesplit[0]] = linesplit[1].strip()
return dictionary
except Exception as e:
errmsg = str(e)
if itrcntr == datalen:
return (dictionary, errmsg)
else:
pass
With this function, I'd expect if it sees that itrcntr is not equal datalen, it would pass and go back to the try block and move on to the next line. But this doesn't happen. INstead it breaks out of the function and continues in the next line in the function caller. How can I make it continue looping till it reaches to the end of the loop in which it will then return the dictionary along with the error message? Or can this not be done with try catch exception handlers?
Unless you want to catch exceptions other than the situation of line.isspace, I wouldn't use a try block at all. Just collect your errors in a list, eg:
errors = []
for line in data:
itrcntr += 1
if line.isspace():
errors.append('File has badly formatted header data at line %d.' % itrcntr)
# then at the end:
if errors:
# do something about it...
If any exception occurred, try clause will be skipped and except clause
will run.
If you raise an exception anywhere in the Try, everything else will be skipped. So if you want the loop to continue, then just don't use Try Except.
Just collect every error message and then return it.

Python : How to use an error out of a try/except block?

I have this try block in my code :
try:
installation('isc-dhcp-server')
except:
print('Oops an error...')
sys.exit(8)
Here in a try/except block the sys.exit(8) will just exit this block and keep an error with code "8". This is just what I want. Now I want to use this except somehere else in a code to avoid somes parts link to this setup. How can I do that ?
I try to put the error in a variable with :
except Exception as NameofError:
And use NameofError with a if statement but this var is not defined in the local space (I think) so I can't use it.
Just initiate a variable before the try-catch block and assign the exception to it
caught_error = None
try:
# some error throwing func
except Exception as e:
caught_error = e
# your error handling code
print(caught_error)
Edit: However, if you still have sys.exit() in your catch block you probably won't have the chance to do anything to the exception given that your program will be terminated already.

If condition check with 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()

How to handle multiple exceptions?

I'm a Python learner, trying to handle a few scenarios:
Reading a file.
Formatting Data.
Manipulating/Copying Data.
Writing a file.
So far, I have:
try:
# Do all
except Exception as err1:
print err1
#File Reading error/ File Not Present
except Exception as err2:
print err2
# Data Format is incorrect
except Exception as err3:
print err3
# Copying Issue
except Exception as err4:
print err4
# Permission denied for writing
The idea of implementing in this fashion is to catch the exact error for all different scenarios. I can do it in all separate try/except blocks.
Is this possible? And reasonable?
Your try blocks should be as minimal as possible, so
try:
# do all
except Exception:
pass
is not something you want to do.
The code in your example won't work as you expect it to, because in every except block you are catching the most general exception type Exception. In fact, only the first except block will ever be executed.
What you want to be doing is having multiple try/except blocks, each one responsible for as few things as possible and catching the most specific exception.
For example:
try:
# opening the file
except FileNotFoundException:
print('File does not exist')
exit()
try:
# writing to file
except PermissionError:
print('You do not have permission to write to this file')
exit()
However, sometimes it is appropriate to catch different types of exceptions, in the same except block or in several blocks.
try:
ssh.connect()
except (ConnectionRefused, TimeoutError):
pass
or
try:
ssh.connect()
except ConnectionRefused:
pass
except TimeoutError:
pass
As DeepSpace stated,
Your try blocks should be as minimal as possible.
If you want to achieve
try:
# do all
except Exception:
pass
Then you might as well do something like
def open_file(file):
retval = False
try:
# opening the file succesful?
retval = True
except FileNotFoundException:
print('File does not exist')
except PermissionError:
print('You have no permission.')
return retval
def crunch_file(file):
retval = False
try:
# conversion or whatever logical operation with your file?
retval = True
except ValueError:
print('Probably wrong data type?')
return retval
if __name__ == "__main__":
if open_file(file1):
open(file1)
if open_file(file2) and crunch_file(file2):
print('opened and crunched')
Yes this is possible.
Just say as example:
try:
...
except RuntimeError:
print err1
except NameError:
print err2
...
Just define the exact Error you want to intercept.

Python: Reverse sentence and write it in another file

I'm trying to reverse the sentence and write it in another file but when I run it, it creates an empty reversed.txt file.
The following two lines are in file input:
Hello World
How is everyone doing?
The file output will have the lines:
dlroW olleH
?gniod enoyreve si woH
My code:
#!/usr/local/bin/python
name = raw_input("Enter name of file: ")
def Reverse(name):
try:
input_file=open(name,"r")
reversed = "reversed.txt"
output_file=open(reversed,"w")
list=input_file.readlines()
for i in range(0,len(list)):
d = int(len(list) - i)
output_file.write(list[d])
except IOError:
print("Cannot open file")
except:
print("Other errors")
else:
print("success")
finally:
print("prints always")
input_file.close()
output_file.close()
#returns reversed
Reverse(name)
When I run this it prints "Other errors". It creates the new file reversed.txt but it`s empty.
There are a couple of things wrong with your code snippet. But this should work better:
#!/usr/local/bin/python
name = raw_input("Enter name of file: ")
def Reverse(name):
try:
input_file=open(name,"r")
reversed = "reversed.txt"
output_file=open(reversed,"w")
for line in input_file.readlines():
output_file.write(line[-2::-1] + "\n")
except IOError:
print("Cannot open file")
except:
print("Other errors")
else:
print("success")
finally:
print("prints always")
input_file.close()
output_file.close()
#returns reversed
Reverse(name)
Here we iterate over the read lines and then use the fact that strings can be viewed as arrays to reverse each line.
EDIT
By using line[-2::-1] we avoid having the ending new line at the start of the line we write to the file. Then we append the "\n" so that each line is properly separated by the new line character.
You can try something like this:
lines=input_file.readlines()
for line in lines:
line = ''.join(list(reversed(line)))
output_file.write(line)
If I were to tell you what's wrong, without improving your implementation (which is definitely possible ;) ) I'd like to suggest a few things:
Indents are super important:
In your code just after the def you have a blank line. This means your function ends before it starts, and your try excepts are just 'floating'.
Your excepts aren't very helpful: You just print small information when catching exceptions. You have no idea why the exception is thrown. A better way to do this is print the exception with your own custom message. Something like:
try:
someCode()
except IOError as ioE:
print "Can't open file! - ", ioE # Change to print() for py3.x
except Exception as otherE:
print "Unknown error! - ", otherE
Initialize variables you intend to use: If you are using a variable, define it! Make sure any flow of loops/try-excepts will end up initializing your vairables. When in doubt, initialize as None (and check for None when using it). In your code, input_file is being used in finally. But if the input_file=open(name,"r") raises an exception, input_file will remain uninitialized causes another exception in finally.
Other than that your implementation can be improved from the other answers.
Hope this helps!

Categories