2011-07-10 10 views
0

私はPythonの初心者で、外部記憶装置(通常は1つ以上のUSBディスク)へのバックアップを実行する最初のモジュールを書き始めました。Python:try/except/elseブロックで例外を発生させて処理の問題を解決する

所望の動作は次のとおり

  1. チェック先(バックアップディスク)場合には、既に実装されています。 destination_was_mountedがTrueまたはFalseになる
  2. destination_was_mounted = Falseの場合、宛先をマウントします。
  3. mountDestinationが失敗した場合は、例外を発生させてループを再開してください。
  4. mountDestinationがokの場合、宛先にcheckfile(およびbackup_dir)が存在するかどうかを確認します。
  5. check_destinationが失敗した場合、例外が発生し、ループが再開します。
  6. 処理を続行します(これはまだコード化されていません)。
  7. 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) 
+2

質問を凝縮できますか?私は完全に失われた... – Blender

+0

"と再起動ループ" ...なぜ?なぜそれが最初に動作しなかった場合、それが2回目に動作することを期待していますか? –

+0

@eryksun、明らかにしてくれてありがとう、そういう意味です。 – jelloir

答えて

0

あなたは、tryブロックでアンマウントコードを持っています。最後に、あなたは単にロギングしているだけです。

+0

ありがとう、これは正しく、最終的にアンマウントコードを移動した後に動作します。また、「NoCheckFile as ex:」という印字を追加して、プロセスに従い、logInfoにlogExecute関数の名前を変更しました。私が読んでいたことから、try:sectionがどのように実行され、考えられたのか混乱していました。オブジェクトは初心者以外の間違いの後でもまだ呼び出されていました。 – jelloir

関連する問題