Working with rmtree
from shutil
module, I made some tests to delete some directories and their content, knowing that rmtree
takes a callback function on onerror
argument, I created a function to keep track of the errors raised, code as below:
def _error_log(func, path, excinfo):
"""
Function that track and record the errors when removing files/dirs
Args:
func (function): The function that raised the error.
path (string): Path to the file/dir that raised the error.
excinfo (tuple): The exception information returned by sys.exc_info().
"""
# Log dict -> key= file/dir fullpath: value= [error class, error message, function that raised the error]
log = {}
# Set the file/dir full path as key with an empty list as value
log.setdefault(path, [])
# Append the error class and message raised from excinfo tuple
log[path].append(excinfo[0].__name__)
log[path].append(excinfo[1].strerror)
# Append the function that raised the error
log[path].append(func.__name__)
return log
# Import
import shutil
# Path to the directory to remove
path_to_remove = r"C:\shutil_test\remove_me"
shutil.rmtree(path_to_remove, onerror=_error_log)
How can I return the log
dict from _error_log
function ? I thought about using a global variable, but it is kind of messy.
I believe the cleanest way is to create a class and store your log as an attribute of the instance. A minimal implementation using your original function:
class RmtreeErrorLogger:
def __init__(self):
# Log dict -> key= file/dir fullpath: value= [error class, error message, function that raised the error]
self.log = {}
def logger(self, func, path, excinfo):
# Set the file/dir full path as key with an empty list as value
self.log.setdefault(path, [])
# Append the error class and message raised from excinfo tuple
self.log[path].append(excinfo[0].__name__)
self.log[path].append(excinfo[1].strerror)
# Append the function that raised the error
self.log[path].append(func.__name__)
To use it:
import shutil
# Path to the directory to remove
path_to_remove = r"C:\shutil_test\remove_me"
logger = RmtreeErrorLogger()
shutil.rmtree(path_to_remove, onerror=logger.logger)
# For example, check if there is any error:
if logger.log:
print('Errors happened')
You could use a callable class to avoid having to say logger.logger
.