There's something weird happening with my code, I have a first function that goes like this :
def function1():
try : #1
#try to open a file
#read file
#return info variable from the file
except : #1
try : #2
#try to open a web page
#read web page
if directory1 not in directorylist :
#create directory1
#change working directory to directory1
else :
#change working directory to directory1
#write web page content in a file
#return info variable from the file
except : #2
try : #3
#try to open a second web page
#print error message 1
except : #3
#print error message 2
#set info variable to None
#return info variable
So this function works perfectly when called in the main program, but when I try to call function1 in another function2, both try#2 and except#2 are executed ! Cause directory1 is created and error message 1 is printed, also my info variable equals None.
How can calling function1 in a second function mess try and except clauses ?
Thank you !
Why is it surprising? try block is supposed to execute till some exception is raised and after that except block will execute. So why does it look like both blocks got executed in spite of an exception?
One of the most likely reasons is there are stuff in try block that has nothing to do with the exception being raised. That's the primary reason for the else block. Refactoring your code as follows might help
try:
# only statements that might raise exception
except SomeException:
# except block
else:
# everything you wanted do if no exception was raised
If it's a big chunk of code, fatter the else block, things are likely to go smoothly.
If an exception is raised while executing body of try #2 , obviously except #2 will be executed. You probably should check what kind of exception is raised and at which line.
Related
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.
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.
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.
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()
I was expecting the following would work but PyDev is returning an error:
try fh = open(myFile):
logging.info("success")
except Exception as e:
logging.critical("failed because:")
logging.critical(e)
gives
Encountered "fh" at line 237, column 5. Was expecting: ":"...
I've looked around and cannot find a safe way to open a filehandle for reading in Python 3.4 and report errors properly. Can someone point me in the correct direction please?
You misplaced the :; it comes directly after try; it is better to put that on its own, separate line:
try:
fh = open(myFile)
logging.info("success")
except Exception as e:
logging.critical("failed because:")
logging.critical(e)
You placed the : after the open() call instead.
Instead of passing in e as a separate argument, you can tell logging to pick up the exception automatically:
try:
fh = open(myFile)
logging.info("success")
except Exception:
logging.critical("failed because:", exc_info=True)
and a full traceback will be included in the log. This is what the logging.exception() function does; it'll call logging.error() with exc_info set to true, producing a message at log level ERROR plus a traceback.