我是Python的新手,並開始編寫我的第一個模塊,它將對外部存儲(通常是一個或多個USB磁盤)執行備份。Python:在try/except/else塊中引發異常,處理順序問題
的期望的行爲是:
- 檢查如果目的地(備份磁盤)已經安裝。 destination_was_mounted變成True或False
- 如果destination_was_mounted = False,則裝入目標。
- 如果mountDestination失敗,引發異常並重新啓動循環。
- 如果mountDestination正常,請檢查目標是否存在checkfile(和backup_dir)。
- 如果check_destination失敗引發異常並重新啓動循環。
- 繼續處理(尚未編碼此)。
- 在任何情況下,如果destination_was_mounted = False,則卸載目標。
問題是,如果check_destination部分引發異常,它將無法卸載目標,即使我已經在最後一節。就好像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)
你可以壓縮你的問題嗎?我完全失去了...... – Blender
「並重新啓動循環」...爲什麼?如果第一次無法正常工作,你爲什麼會期待它再次工作? –
@eryksun,感謝您的澄清,是的,這就是我的意思。 – jelloir