Python:在 try/except/else 块中引发异常,处理顺序问题
Posted
技术标签:
【中文标题】Python:在 try/except/else 块中引发异常,处理顺序问题【英文标题】:Python: raising exception in try/except/else block, processing order problem 【发布时间】:2011-07-10 01:16:19 【问题描述】:我是 Python 新手,已经开始编写我的第一个模块,该模块将执行备份到外部存储(通常是一个或多个 USB 磁盘)。
期望的行为是:
-
检查目标(备份磁盘)是否已经挂载。 destination_was_mounted 变为 True 或 False
如果 destination_was_mounted = False 则挂载目标。
如果 mountDestination 失败,引发异常并重新启动循环。
如果 mountDestination 正常,请检查目标上是否存在 checkfile(和 backup_dir)。
如果 check_destination 失败引发异常并重新启动循环。
继续处理(尚未编码)。
在任何情况下,如果destination_was_mounted = False,则卸载目标。
问题是,如果 check_destination 部分引发异常,即使我在 finally 部分中有该目标,它也无法卸载目标。就好像destination_was_mounted 变成了True,即使它本来应该是False。或者好像 check_destination 在 mount_destination 之前运行,即使它在它之后。
我的参考资料(在查看 python 文档和我的学习 Python 书籍中):
Python: How to tell the for loop to continue from a function?
How to retry after exception in python?
How to get back to the for loop after exception handling
#!/usr/bin/env python3.1
import sys
import os
import os.path
import subprocess
import configparser
CONFIGFILE = 'backup.ini'
# do i need this?
config =
config = configparser.ConfigParser()
config.read(CONFIGFILE)
backup_sources = sorted(config.sections()[1:])
class NoCheckFile(Exception):
pass
def mountDestination(destination):
return subprocess.check_call(['mount', destination])
def unMountDestination(destination):
return subprocess.check_call(['umount', destination])
def checkDestination(destination, backup_dir, checkfile):
return os.path.exists(destination + '/' + backup_dir + '/' + checkfile)
''' exception handlers '''
# perhaps add another arg like 0 or 1 for success/failure
def handleCalledProcessError(ex):
print('Exception: ' + str(ex))
def handleNoCheckFile(ex):
print('Exception: ' + str(ex))
# rename me once I work out logging
def logExecute(result):
print('Info: ' + str(result))
# can I pass logging output here
def main():
for section in backup_sources:
item = dict(config.items(section))
destination = item['destination']
destination_was_mounted = os.path.ismount(destination)
backup_dir = item['backup_dir']
checkfile = item['checkfile']
try:
''' check destination_was_mounted and mount destination if required '''
mount_destination = None
unmount_destination = None
if not destination_was_mounted:
mount_destination = mountDestination(destination)
''' check that checkfile exists in backup_dir '''
check_destination = checkDestination(destination, backup_dir, checkfile)
if not check_destination:
raise NoCheckFile('no checkfile found')
''' lvm snapshot, mount and source path update '''
''' backup engine code here '''
''' check destination_was_mounted and um-mount destination if required '''
if not destination_was_mounted:
unmount_destination = unMountDestination(destination)
except subprocess.CalledProcessError as ex:
print(destination, 'mounted before loop start: ', destination_was_mounted)
handleCalledProcessError(ex)
except NoCheckFile as ex:
handleNoCheckFile(ex)
else:
print(destination, 'mounted before loop start: ', destination_was_mounted)
logExecute(mount_destination)
logExecute(check_destination)
finally:
print('should always see me')
logExecute(unmount_destination)
# return to say True or False
# this should be where email reports etc. go
if __name__ == '__main__':
main()
backup.ini 文件的相关部分是:
[general]
[1]
DESTINATION = /mnt/backup2
BACKUP_DIR = BACKUP2
CHECKFILE = .checkfile
[2]
DESTINATION = /mnt/backup1
BACKUP_DIR = BACKUP1
CHECKFILE = .checkfile
输出如下所示 - 我在 [1] 和 [2] 中指定的挂载点附加了 2 个备份磁盘,并且故意没有为 [1] 创建检查文件以进行测试。
> umount /mnt/backup1
umount: /mnt/backup1: not mounted
> umount /mnt/backup2
umount: /mnt/backup2: not mounted
> mugsyback.py
Exception: no checkfile found
should always see me
Info: None
/mnt/backup1 mounted before loop start: False
Info: 0
Info: True
should always see me
Info: 0
> mount
...
/dev/sdc1 on /mnt/backup2 type ext3 (rw)
【问题讨论】:
你能把你的问题浓缩一下吗?我完全迷路了...... “然后重启循环”...为什么?如果第一次没有工作,你为什么期望它第二次工作? @eryksun,感谢您的澄清,是的,这就是我的意思。 【参考方案1】:您在 try 块中有卸载代码。最后,您只是在登录。
【讨论】:
谢谢,这是正确的,并且在将卸载代码移动到 finally: 后有效。我还在“除了 NoCheckFile as ex:”中添加了一个打印,这有助于我遵循该过程并将 logExecute 函数重命名为 logInfo。从我正在做的阅读中,我对 try: 部分的执行方式感到困惑,并认为:在出现 except - newbie 错误后仍然调用对象。以上是关于Python:在 try/except/else 块中引发异常,处理顺序问题的主要内容,如果未能解决你的问题,请参考以下文章
python 中的 try/except/else/finally语句
python try/except/else/finally执行顺序
Python入门教程第54篇 异常处理之try…except…else
python中的try/except/else/finally语句