how to catch error in finally block in python

醉酒当歌 提交于 2020-01-07 05:56:09

问题


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', '%s@abc.com'%email_address))
        message['From'] = email.utils.formataddr(('Author', '%s@abc.com'%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 "%s@abc.com, %s@abc.com, %s "%(email_address,email_address,message.as_string())
        server.sendmail('%s@abc.com'%email_address, "%s@abc.com"%email_address, message.as_string())
    finally:
        server.quit()

回答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()



回答2:


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', '%s@abc.com'%email_address))
    message['From'] = email.utils.formataddr(('Author', '%s@abc.com'%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 "%s@abc.com, %s@abc.com, %s "%(email_address,email_address,message.as_string())
        server.sendmail('%s@abc.com'%email_address, "%s@abc.com"%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 = "%s@abc.com" % 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()


来源:https://stackoverflow.com/questions/43586041/how-to-catch-error-in-finally-block-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!