如何从shutil.rmtree的onerror回调函数中返回一个值?

huangapple go评论62阅读模式
英文:

How to return a value from onerror callback in shutil.rmtree

问题

你可以将log字典作为_error_log函数的参数传递,并在函数内部进行更新。这样,当函数执行完毕后,你就可以直接返回更新后的log字典了。以下是修改后的代码示例:

def _error_log(log, func, path, excinfo):
    """
    Function that track and record the errors when removing files/dirs

    Args:
        log (dict): The dictionary to store the error log.
        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().
    """

    # 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__)


# Import
import shutil

# Path to the directory to remove
path_to_remove = r"C:\shutil_test\remove_me"

log = {}
shutil.rmtree(path_to_remove, onerror=lambda func, path, excinfo: _error_log(log, func, path, excinfo))

# Now you can use the 'log' dictionary outside the function
print(log)

在修改后的代码中,我们将log字典作为参数传递给_error_log函数,并在函数内部进行更新。在调用shutil.rmtree时,我们使用了一个lambda函数来调用_error_log函数,并将log字典作为参数传递进去。这样,在_error_log函数内部对log字典的更新就会反映在外部的log变量上。最后,你可以在函数外部使用log字典来获取错误日志信息。

英文:

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.

答案1

得分: 1

我相信最简洁的方法是创建一个类,并将日志存储为实例的属性。以下是使用你的原始函数进行最小实现的示例:

class RmtreeErrorLogger:
    def __init__(self):
        # 日志字典 -> 键=文件/目录完整路径,值= [错误类,错误消息,引发错误的函数]
        self.log = {}

    def logger(self, func, path, excinfo):
        # 将文件/目录完整路径设置为键,值为空列表
        self.log.setdefault(path, [])
    
        # 将从excinfo元组中引发的错误类和消息追加到列表中
        self.log[path].append(excinfo[0].__name__)
        self.log[path].append(excinfo[1].strerror)
    
        # 追加引发错误的函数
        self.log[path].append(func.__name__)

使用方法如下:

import shutil

# 要删除的目录路径
path_to_remove = r"C:\shutil_test\remove_me"
logger = RmtreeErrorLogger()

shutil.rmtree(path_to_remove, onerror=logger.logger)

# 例如,检查是否有任何错误:
if logger.log:
    print('发生错误')

你可以使用可调用的类来避免使用logger.logger这样的语法。

英文:

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.

huangapple
  • 本文由 发表于 2023年8月9日 17:49:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866533.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定