如何捕获Python中的finally块中的错误

问题描述:

我可以看到try-catch上的几个主题,但似乎没有讨论如果有任何来自finally块的错误。我发现如果它在finally块中,错误不会被处理。什么是最后管理的理想方式?如何捕获Python中的finally块中的错误

例如,下面是一个邮件功能。如果try块中有任何错误,最后将执行本身未启动的quit方法,因此发生未处理的错误。那么确保在finally块中不会出现错误会更好吗?

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() 
+0

为什么你就不能换它在另一个'尝试'? –

+0

我可以。只是想知道这是否是正确的做法。 – kten

+1

不是。正确的做法是避免将你的整个函数包装在try块中。 –

不要把一串代码(做不同的事情)为一个的try/except块,但你可以轻松地在finally块添加一个if/else条件:

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

由于您finally块只是用来保证服务器的连接正确关闭什么,答案显然是只包裹在try块中的相关部分:

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

的静止更好的解决办法是将拆分每一个定义明确的责任不同的功能,这个代码 - 准备的消息,让到服务器的连接等,即:

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