Python:在try / except / else块中引发异常,处理顺序问题

时间:2011-07-10 01:16:19

标签: python loops exception-handling

我是Python的新手并且已经开始编写我的第一个模块,它将执行备份到外部存储(通常是一个或多个USB磁盘)。

理想的行为是:

  1. 检查是否已安装目标(备份磁盘)。 destination_was_mounted变为True或False
  2. 如果destination_was_mounted = False,则安装目的地。
  3. 如果mountDestination失败,则引发异常并重新启动循环。
  4. 如果mountDestination正常,请检查目标上是否存在checkfile(和backup_dir)。
  5. 如果check_destination失败,则引发异常并重新启动循环。
  6. 继续处理(尚未编码)。
  7. 在任何情况下,如果destination_was_mounted = False,则取消安装目的地。
  8. 问题在于,如果check_destination部分引发异常,则即使我在finally部分中有该目的,也无法卸载目标。这就好像destination_was_mounted变为True,即使它应该是假的。或者好像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)
    

1 个答案:

答案 0 :(得分:0)

您在try块中有卸载代码。最后,你只是记录。