如何捕获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()
答
不要把一串代码(做不同的事情)为一个的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()
为什么你就不能换它在另一个'尝试'? –
我可以。只是想知道这是否是正确的做法。 – kten
不是。正确的做法是避免将你的整个函数包装在try块中。 –