0

I could see several topics on try - catch but doesnt seem to discuss errors if any from finally block itself. I found that the error is not handled if it is in finally block. What would be the ideal way to manage finally?

For eg. below is a mail function. if there is any error in try block, finally will execute the quit method which itself is not initiated so an unhandled error occurs. So is it better to ensure there is no errors occur in finally block?

def send_email(ldap, email_address, password, msg): try: message = MIMEMultipart('alternative') message['To'] = email.utils.formataddr(('Recipient', '%[email protected]'%email_address)) message['From'] = email.utils.formataddr(('Author', '%[email protected]'%email_address)) message['Subject'] = 'Sample subject' text = "%s"%msg html = MIMEText('<html><head></head><h2>data</h2><body><p>%s</p></body></html>'%msg,'html') message.attach(html) server = smtplib.SMTP(host="ip",port=0) server.set_debuglevel(True) # identify ourselves, prompting server for supported features server.ehlo() if server.has_extn('STARTTLS'): server.starttls() server.ehlo() server.login(ldap, password) print "%[email protected], %[email protected], %s "%(email_address,email_address,message.as_string()) server.sendmail('%[email protected]'%email_address, "%[email protected]"%email_address, message.as_string()) finally: server.quit() 
4
  • Why can't you just wrap it in another try? Commented Apr 24, 2017 at 10:47
  • i can . just wanted to know if it is the right approach. Commented Apr 24, 2017 at 10:48
  • 1
    It isn't. The right approach is to avoid wrapping your whole function in the try block. Commented Apr 24, 2017 at 10:50
  • To expand on bruno's answer, what are you attempting to achieve with this 'try:' block? It doesn't seem to be adding any value. Think about the various things that could go wrong and what you want to happen if they do, then use try/except/finally to achieve that desired behavior. Not all code needs to be wrapped in exception handling. Incidentally, exception handling isn't really for debugging, it's for responding appropriately to things that go wrong when the application is being used. Commented Apr 24, 2017 at 10:58

2 Answers 2

1

Dont put a bunch of code (doing different things) into one try/except block, but you can easily add an if/else condition in your finally block:

def send_email(ldap, email_address, password, msg): server = None #make sure server variable is always defined. try: ... server = smtplib.SMTP(...) ... finally: if server and isinstance(x, smtplib.SMTP): server.quit() 
Sign up to request clarification or add additional context in comments.

Comments

1

Since your finally block is only used to ensure the server connection is properly closed whatever, the obvious answer is to only wrap the relevant part in the try block:

def send_email(ldap, email_address, password, msg): message = MIMEMultipart('alternative') message['To'] = email.utils.formataddr(('Recipient', '%[email protected]'%email_address)) message['From'] = email.utils.formataddr(('Author', '%[email protected]'%email_address)) message['Subject'] = 'Sample subject' text = "%s"%msg html = MIMEText('<html><head></head><h2>data</h2><body><p>%s</p></body></html>'%msg,'html') message.attach(html) server = smtplib.SMTP(host="ip",port=0) # now you can start the try block: try: server.set_debuglevel(True) # identify ourselves, prompting server for supported features server.ehlo() if server.has_extn('STARTTLS'): server.starttls() server.ehlo() server.login(ldap, password) print "%[email protected], %[email protected], %s "%(email_address,email_address,message.as_string()) server.sendmail('%[email protected]'%email_address, "%[email protected]"%email_address, message.as_string()) finally: server.quit() 

A still better solution would be to split this code in distinct functions each with a single well-defined responsability - preparing the message, getting a connection to the server etc, ie:

def prepare_message(sender, recipient, subject, msg): message = MIMEMultipart('alternative') message['To'] = email.utils.formataddr(('Recipient', recipient)) message['From'] = email.utils.formataddr(('Author', sender)) message['Subject'] = subject #text = "%s" % msg # this one is useless html = MIMEText(""" <html> <head></head> <body> <h2>data</h2> <p>%s</p> </body> </html>""" % msg, 'html' ) message.attach(html) return message def connect(ldap, password): server = smtplib.SMTP(host="ip",port=0) server.set_debuglevel(True) # identify ourselves, prompting server for supported features server.ehlo() if server.has_extn('STARTTLS'): server.starttls() server.ehlo() server.login(ldap, password) return server def send_email(ldap, email_address, password, msg): sender = recipient = "%[email protected]" % email_address message = prepare_message(sender, recipient, 'Sample subject', msg) server = connect(ldap, password) try: server.sendmail(sender, recipient, message.as_string()) finally: server.quit() 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.