【问题标题】:how to catch error in finally block in python如何在python的finally块中捕获错误
【发布时间】:2017-04-24 10:45:18
【问题描述】:

我可以看到关于 try - catch 的几个主题,但似乎没有讨论最终阻塞本身的错误。我发现如果它在 finally 块中,则不会处理错误。最终管理的理想方式是什么?

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

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

【问题讨论】:

  • 你为什么不能把它换成另一个try
  • 我可以。只是想知道这是否是正确的方法。
  • 不是。正确的做法是避免将整个函数包装在 try 块中。
  • 为了扩展 bruno 的答案,你想用这个 'try:' 块来实现什么?它似乎没有增加任何价值。想一想可能出错的各种事情以及如果它们出错你希望发生什么,然后使用 try/except/finally 来实现所需的行为。并非所有代码都需要包含在异常处理中。顺便说一句,异常处理并不是真正用于调试,而是用于对应用程序使用时出现的问题做出适当的响应。

标签: python exception exception-handling try-catch


【解决方案1】:

不要将一堆代码(做不同的事情)放在一个 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()

【讨论】:

    【解决方案2】:

    由于您的 finally 块仅用于确保服务器连接正确关闭,因此显而易见的答案是仅将相关部分包装在 try 块中:

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

    更好的解决方案是将此代码拆分为不同的函数,每个函数都有一个明确定义的职责 - 准备消息、获取与服务器的连接等,即:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-27
      • 2012-02-11
      • 1970-01-01
      • 2016-05-29
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      相关资源
      最近更新 更多