私はPythonの初心者で、外部記憶装置(通常は1つ以上のUSBディスク)へのバックアップを実行する最初のモジュールを書き始めました。Python:try/except/elseブロックで例外を発生させて処理の問題を解決する
所望の動作は次のとおり
- チェック先(バックアップディスク)場合には、既に実装されています。 destination_was_mountedがTrueまたはFalseになる
- destination_was_mounted = Falseの場合、宛先をマウントします。
- mountDestinationが失敗した場合は、例外を発生させてループを再開してください。
- mountDestinationがokの場合、宛先にcheckfile(およびbackup_dir)が存在するかどうかを確認します。
- check_destinationが失敗した場合、例外が発生し、ループが再開します。
- 処理を続行します(これはまだコード化されていません)。
- destination_was_mounted = Falseの場合は、いずれの条件でも宛先をアンマウントします。
問題があるのは、check_destination部分が例外を発生させた場合、最終節にあるにもかかわらず宛先をアンマウントできないという問題です。それは、たとえそれがFalseであったとしても、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)
質問を凝縮できますか?私は完全に失われた... – Blender
"と再起動ループ" ...なぜ?なぜそれが最初に動作しなかった場合、それが2回目に動作することを期待していますか? –
@eryksun、明らかにしてくれてありがとう、そういう意味です。 – jelloir