簡體   English   中英

如果 try 塊的某個方面失敗,則繼續運行代碼,但仍會引發異常

[英]Continue running code if one aspect of a try block fails, but still raise the exception

作為將 excel 文件處理為具有多個 Python 函數的不同格式的更大腳本的一部分,我有這個 function 來實際運行所有其他函數:

print = logging.info
class MyException(Exception):
    pass
@catch_exception_and_send_email
def validation_and_processing(file_list):
    '''
    This function the file list and runs each file in the directory through the validation and processing functions.
    
    args:
        file_list : output file path     
    '''
    exceptions = []
    for file in files:
        try:
            if file.startswith('Nomura'):
                check_filename_format(input_file = file)
                nomura = nomura_validation(input_dir = input_dir, file = file)
                nomura_df = nomura_processing(nomura)
                write_output(path=output_dir, filename=file, dataframe=nomura_df)
                shutil.move(input_dir+file, archive_dir+file)
                print("Congratulations! {} dealer file processed successfully on {} at {}".format(file, date, time))

            elif file.startswith('MSTN'):
                check_filename_format(input_file = file)
                morgan = morgan_validation(input_dir = input_dir, file = file) 
                morgan_df = morgan_processing(morgan)
                write_output(path=output_dir, filename=file, dataframe=morgan_df)
                shutil.move(input_dir+file, archive_dir+file)
                print("Congratulations! {} dealer file processed successfully on {} at {}".format(file, date, time))

            elif file.startswith('JPM'):
                check_filename_format(input_file = file)
                jpm, input_file = jpm_validation(input_dir = input_dir, file = file)
                jpm = jpm_processing(jpm, input_file)
                write_output(path=output_dir, filename=file, dataframe=jpm)
                shutil.move(input_dir+file, archive_dir+file)
                print("Congratulations! {} dealer file processed successfully on {} at {}".format(file, date, time))

            elif file.startswith('BofA'):
                check_filename_format(input_file = file)
                bofa_not_ginnie, bofa_ginnie = bofa_validation(input_dir=input_dir, file=file)
                bofa_final = bofa_processing(df1=bofa_not_ginnie, df2=bofa_ginnie, input_file=file)       
                write_output(path=output_dir, filename=file, dataframe=bofa_final)
                shutil.move(input_dir+file, archive_dir+file)
                print("Congratulations! {} dealer file processed successfully on {} at {}".format(file, date, time))

            elif file.startswith('CITI'):
                check_filename_format(input_file = file)
                citi = citi_validation(input_dir=input_dir, file=file)
                citi_final = citi_processing(df=citi, input_file=file)    
                write_output(path=output_dir, filename=file, dataframe=citi_final)
                shutil.move(input_dir+file, archive_dir+file)
                print("Congratulations! {} dealer file processed successfully on {} at {}".format(file, date, time))
                
        except (OSError, IOError, MyException):
            # This should cast a wide net since:
            # In 3.3, IOError became an alias for OSError, 
            # and FileNotFoundError is a subclass of OSError
            # also catches PermissionError
            # Source: https://stackoverflow.com/questions/15032108/pythons-open-throws-different-errors-for-file-not-found-how-to-handle-b/15032444#15032444
            # Logs the error appropriately.
            logging.error("Error with file:" + file)
            continue
        except Exception as e:
            # Reraise exception adding info about which file
            pass
            raise Exception("Error with file:", file) from e
    return exceptions

這個想法是,如果文件的 function 之一失敗,它應該引發異常,但仍應確保嘗試運行所有其他文件。 當我運行一個文件格式不正確的測試用例時,它會引發該文件的錯誤並成功完成該文件之前目錄中出現的文件,但不是之后的文件。 如果發生錯誤,我如何修改我的代碼以完成引發的錯誤(如果一個文件不正確,我需要代碼最終失敗,因為發送了 email 異常並且日志文件更新了錯誤),但仍然運行其他文件是否正確。

這是我構建日志文件的代碼。 我使用catch_exception_and_send_email作為裝飾器 function 用於腳本中的其他函數,以防它們引發異常。

now = datetime.now()
date = now.strftime("%m_%d_%Y") 
time = now.strftime("%H_%M_%S")
log_filename = "log_" + date + "_" + time + ".txt"

#Initialize log file
logging.basicConfig(filename=log_filename, level=logging.DEBUG, format='%(asctime)s %(levelname)s %(name)s %(message)s', force = True)
logger=logging.getLogger(__name__)
logging.getLogger('PIL').setLevel(logging.WARNING)

'''
The below function is a decorator function that checks every function in the file at runtime for exceptions,
and updates the log file and sends an email with details of exception
'''

def catch_exception_and_send_email(func):
    def exception_catcher(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            print(e)
            send_error_email(exception=e, message="An exception {} occurred in {}".format(e, func.__name__))
            logging.exception('Oh no! {} On {} at {} in: {} function.'.format(e, date, time, func.__name__), exc_info = False)
            sys.exit(1)
    return exception_catcher

您需要能夠只保留異常:

def validation_and_processing(file_list):
    '''
    This function the file list and runs each file in the directory through the validation and processing functions.
    
    args:
        file_list : output file path     
    '''
    exceptions = []
    for file in files:
        try:
            if file.startswith('Nomura'):
                ...
                ...

        except Exception as e:      
            exceptions.append(e)

    return exceptions

目標是:

  • 記錄文件的預期異常並繼續處理
  • 引發異常並停止其他異常

代碼

import traceback
import logging

def validation_and_processing(file_list):
    '''
    This function the file list and runs each file in the directory through the validation and processing functions.
    
    args:
        file_list : output file path     
    '''
    for file in files:
        try:
            if file.startswith('Nomura'):
                ...
                ...
        except (OSError, IOError, CustomExceptionName):
            # This should cast a wide net since:
            # In 3.3, IOError became an alias for OSError, 
            # and FileNotFoundError is a subclass of OSError
            # also catches PermissionError
            # Source: https://stackoverflow.com/questions/15032108/pythons-open-throws-different-errors-for-file-not-found-how-to-handle-b/15032444#15032444
            # CustomExceptionName class similar to: https://stackoverflow.com/questions/1319615/proper-way-to-declare-custom-exceptions-in-modern-python/53469898#53469898 
            # Logs the error appropriately.
            logging.exception("Error with file:" + file)
            continue     # continue processing

       except Exception as e:
            # Reraise exception adding info about which file
            raise Exception("Error with file:", file) from e
            

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM