YOLOv11-ultralytics-8.3.67部分代码阅读笔记-files.py

news/2025/2/8 17:58:08 标签: YOLO, 笔记, 深度学习

files.py

ultralytics\utils\files.py

目录

files.py

1.所需的库和模块

2.class WorkingDirectory(contextlib.ContextDecorator): 

3.def spaces_in_path(path): 

4.def increment_path(path, exist_ok=False, sep="", mkdir=False): 

5.def file_age(path=__file__): 

6.def file_date(path=__file__): 

7.def file_size(path): 

8.def get_latest_run(search_dir="."): 

9.def update_models(model_names=("yolo11n.pt",), source_dir=Path("."), update_names=False): 


1.所需的库和模块

# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license

import contextlib
import glob
import os
import shutil
import tempfile
from contextlib import contextmanager
from datetime import datetime
from pathlib import Path

2.class WorkingDirectory(contextlib.ContextDecorator): 

# 这段代码定义了一个名为 WorkingDirectory 的类,它是一个上下文管理器,用于临时更改当前工作目录。这个类继承自 contextlib.ContextDecorator ,这意味着它可以作为上下文管理器( with 语句)使用,也可以作为装饰器使用。
# 定义了一个名为 WorkingDirectory 的类,继承自 contextlib.ContextDecorator 。
# contextlib.ContextDecorator 是一个辅助类,允许上下文管理器同时用作装饰器。这意味着这个类既可以使用 with 语句,也可以用于装饰函数。
class WorkingDirectory(contextlib.ContextDecorator):
    # 用于临时更改工作目录的上下文管理器和装饰器。
    # 此类允许使用上下文管理器或装饰器临时更改工作目录。
    # 它确保在上下文或装饰函数完成后恢复原始工作目录。
    # 方法:
    # __enter__:将当前目录更改为指定目录。
    # __exit__:在退出上下文时恢复原始工作目录。
    # 示例:
    # 用作上下文管理器:
    # >>> with WorkingDirectory('/path/to/new/dir'):
    # >>> # 在新目录中执行操作
    # >>> pass
    # 用作装饰器:
    # >>> @WorkingDirectory('/path/to/new/dir')
    # >>> def some_function():
    # >>> # 在新目录中执行操作
    # >>> pass
    """
    A context manager and decorator for temporarily changing the working directory.

    This class allows for the temporary change of the working directory using a context manager or decorator.
    It ensures that the original working directory is restored after the context or decorated function completes.

    Attributes:
        dir (Path): The new directory to switch to.
        cwd (Path): The original current working directory before the switch.

    Methods:
        __enter__: Changes the current directory to the specified directory.
        __exit__: Restores the original working directory on context exit.

    Examples:
        Using as a context manager:
        >>> with WorkingDirectory('/path/to/new/dir'):
        >>> # Perform operations in the new directory
        >>>     pass

        Using as a decorator:
        >>> @WorkingDirectory('/path/to/new/dir')
        >>> def some_function():
        >>> # Perform operations in the new directory
        >>>     pass
    """

    # 定义了类的初始化方法 __init__ ,接受一个参数。
    # 1.new_dir :要切换到的新目录。
    def __init__(self, new_dir):
        # 在实例化时将工作目录设置为‘new_dir’,以便与上下文管理器或装饰器一起使用。
        """Sets the working directory to 'new_dir' upon instantiation for use with context managers or decorators."""
        # 将传入的 new_dir 赋值给实例变量 self.dir ,表示 目标目录 。
        self.dir = new_dir  # new dir
        # 使用 Path.cwd() 获取当前工作目录,并通过 resolve() 方法解析为绝对路径。
        # 将 当前工作目录 存储在实例变量 self.cwd 中,用于在上下文退出时恢复。
        self.cwd = Path.cwd().resolve()  # current dir

    # 定义了 __enter__ 方法,这是上下文管理器进入上下文时调用的方法。
    def __enter__(self):
        # 进入上下文后将当前工作目录更改为指定目录。
        """Changes the current working directory to the specified directory upon entering the context."""

        # os.chdir(path)
        # os.chdir() 函数是 Python 的标准库 os 模块中的一个函数,用于更改当前工作目录。
        # 参数 :
        # path :要更改到的目标目录的路径。
        # 功能描述 :
        # os.chdir(path) 函数将当前工作目录更改为 path 指定的目录。如果 path 不存在或无法访问,将抛出一个异常。
        # 异常处理 :
        # 当尝试更改到一个不存在或无法访问的目录时, os.chdir() 会抛出 FileNotFoundError 或 PermissionError 异常。因此,在实际使用中,可能需要捕获这些异常来处理错误情况。

        # 使用 os.chdir(self.dir) 切换到目标目录 self.dir 。
        # 当进入上下文时,当前工作目录会被切换到指定的目录。
        os.chdir(self.dir)

    # 定义了 __exit__ 方法,这是上下文管理器退出上下文时调用的方法。 参数 :
    # 1.exc_type :异常类型(如果有异常发生)。
    # 2.exc_val :异常值(如果有异常发生)。
    # 3.exc_tb :异常的回溯信息(如果有异常发生)。
    # # noqa 是一个注释,通常用于告诉代码检查工具(如 flake8 )忽略这一行的某些检查。
    def __exit__(self, exc_type, exc_val, exc_tb):  # noqa
        # 退出上下文时恢复原始工作目录。
        """Restores the original working directory when exiting the context."""
        # 在退出上下文时,使用 os.chdir(self.cwd) 将工作目录恢复到进入上下文之前的目录。
        os.chdir(self.cwd)
# WorkingDirectory 类是一个上下文管理器,用于临时更改当前工作目录。它的主要功能包括。临时切换目录:在进入上下文时切换到指定目录,在退出上下文时恢复到原来的目录。支持 with 语句和装饰器:由于继承自 contextlib.ContextDecorator ,这个类既可以作为上下文管理器使用,也可以作为装饰器使用。
# 使用示例 :
# 作为上下文管理器使用 :
# with WorkingDirectory("/path/to/new/directory"):
#     # 在这个代码块中,当前工作目录被切换到 "/path/to/new/directory"
#     print("Current directory:", Path.cwd())
# # 退出上下文后,工作目录恢复到原来的目录
# print("Current directory after with block:", Path.cwd())
# 作为装饰器使用 :
# @WorkingDirectory("/path/to/new/directory")
# def my_function():
#     # 在这个函数中,当前工作目录被切换到 "/path/to/new/directory"
#     print("Current directory in function:", Path.cwd())
# my_function()
# # 函数执行完成后,工作目录恢复到原来的目录
# print("Current directory after function call:", Path.cwd())
# 这种设计使得 WorkingDirectory 类非常灵活,可以在需要临时更改工作目录的场景中方便地使用。

3.def spaces_in_path(path): 

# 这段代码定义了一个名为 spaces_in_path 的上下文管理器,用于处理路径中包含空格的情况。它通过临时替换路径中的空格为下划线,避免在某些工具或命令中因空格导致的问题。
# 使用 contextlib.contextmanager 装饰器,将 spaces_in_path 函数定义为一个上下文管理器。这种写法比直接定义类更简洁,适用于简单的上下文管理逻辑。
@contextmanager
# 定义了一个函数 spaces_in_path ,接受一个参数。
# 1.path :需要处理的文件或目录路径。
def spaces_in_path(path):
    # 上下文管理器处理名称中带有空格的路径。如果路径包含空格,它会用下划线替换它们,将文件/目录复制到新路径,执行上下文代码块,然后将文件/目录复制回其原始位置。
    # Yields:
    # (Path):如果存在空格,则用下划线替换临时路径中的空格,否则为原始路径。
    # 示例:
    # 使用上下文管理器处理带有空格的路径:
    # >>> from ultralytics.utils.files import space_in_path
    # >>> with space_in_path('/path/with space') as new_path:
    # >>> # 您的代码在这里
    """
    Context manager to handle paths with spaces in their names. If a path contains spaces, it replaces them with
    underscores, copies the file/directory to the new path, executes the context code block, then copies the
    file/directory back to its original location.

    Args:
        path (str | Path): The original path that may contain spaces.

    Yields:
        (Path): Temporary path with spaces replaced by underscores if spaces were present, otherwise the original path.

    Examples:
        Use the context manager to handle paths with spaces:
        >>> from ultralytics.utils.files import spaces_in_path
        >>> with spaces_in_path('/path/with spaces') as new_path:
        >>> # Your code here
    """
    # If path has spaces, replace them with underscores    如果路径中有空格,则用下划线替换。
    # 检查路径中是否包含空格。如果路径是 Path 对象或字符串,将其转换为字符串后检查是否包含空格。
    if " " in str(path):
        # 检查输入的 path 是否是字符串类型,并将结果存储在变量 string 中。这用于后续决定返回的路径类型(字符串或 Path 对象)。
        string = isinstance(path, str)  # input type
        # 将输入的路径统一转换为 Path 对象,方便后续操作。
        path = Path(path)

        # Create a temporary directory and construct the new path    创建临时目录并构造新路径。

        # tempfile.TemporaryDirectory()
        # tempfile.TemporaryDirectory() 是 Python 标准库 tempfile 模块中的一个函数,用于创建一个临时目录。这个临时目录在创建时是空的,并且在使用完毕后可以自动删除。
        # 函数定义 :
        # with TemporaryDirectory() as tmp_dir:
        #     print(tmp_dir)
        # 参数。TemporaryDirectory() 可以接受一些参数来定制临时目录的行为 :
        # dir :指定一个特定的目录,在该目录下创建临时目录。如果没有指定,则使用系统默认的临时文件目录。
        # prefix :指定临时目录的前缀。
        # suffix :指定临时目录的后缀。
        # ignore_cleanup_errors :一个布尔值,指定是否忽略清理时发生的错误,默认为 False 。
        # cleanup :一个布尔值,指定是否在退出上下文管理器时清理临时目录,默认为 True 。
        # mode :设置目录的权限模式,默认为 0o700 。
        # 在示例中, TemporaryDirectory() 被用作上下文管理器,它创建了一个临时目录,并在 with 块中提供了这个目录的路径。当 with 块执行完毕后,临时目录及其内容将被自动删除。
        # TemporaryDirectory() 是处理需要临时文件或目录的场合的有用工具,特别是在测试、临时文件处理或任何需要临时存储的场合。使用临时目录可以避免临时文件对主文件系统的污染,并确保资源在使用后被正确清理。

        # 使用 tempfile.TemporaryDirectory() 创建一个临时目录,用于存放处理后的文件或目录。 tmp_dir 是 临时目录的路径 。
        with tempfile.TemporaryDirectory() as tmp_dir:
            # 构造临时路径 tmp_path ,将原始路径的文件名或目录名中的空格替换为下划线。
            # 例如,如果原始路径是 /path/to/my folder ,则临时路径可能是 /tmp/tempdir/my_folder 。
            tmp_path = Path(tmp_dir) / path.name.replace(" ", "_")

            # Copy file/directory    复制文件/目录。
            # 如果原始路径是一个目录。
            if path.is_dir():
                # tmp_path.mkdir(parents=True, exist_ok=True)

                # shutil.copytree(src, dst, symlinks=False, ignore=None, dirs_exist_ok=False)
                # shutil.copytree() 是 Python 标准库 shutil (shell utilities)模块中的一个函数,用于递归地复制一个目录到另一个位置。这个函数会复制目录中的所有内容,包括子目录和文件。
                # 参数 :
                # src :源目录的路径。
                # dst :目标目录的路径。如果目标目录已经存在,并且 dirs_exist_ok 参数为 False ,则会抛出一个 FileExistsError 异常。
                # symlinks :一个布尔值,指定是否复制符号链接。默认为 False ,即不复制符号链接。
                # ignore :一个可选的回调函数,用于排除不需要复制的文件或目录。
                # dirs_exist_ok :一个布尔值,指定如果目标目录已经存在,是否允许复制操作继续。默认为 False ,如果目标目录存在,则会抛出异常。
                # shutil.copytree() 是一个强大的工具,用于复制整个目录树,常用于备份、同步文件或在测试中创建测试数据目录。

                # 使用 shutil.copytree 将整个目录复制到临时路径。 dirs_exist_ok=True 参数允许目标目录已存在时继续复制。
                shutil.copytree(path, tmp_path)
            #  如果原始路径是一个文件。
            elif path.is_file():
                # 确保临时路径的父目录存在。
                tmp_path.parent.mkdir(parents=True, exist_ok=True)

                # shutil.copy2(src, dst, *, follow_symlinks=True)
                # shutil.copy2() 是 Python 标准库 shutil (shell utilities)模块中的一个函数,用于复制文件,同时尝试保留原文件的元数据,如修改时间和权限等。
                # 参数 :
                # src :源文件的路径。
                # dst :目标文件的路径。如果目标文件已经存在,将会被覆盖。
                # follow_symlinks :一个布尔值,默认为 True ,表示是否跟随符号链接。如果设置为 False ,则会复制符号链接本身而不是链接指向的文件。
                # 功能描述 :
                # shutil.copy2() 函数将一个文件从 src 路径复制到 dst 路径,并尝试保留源文件的元数据。如果 follow_symlinks 参数为 True ,它将复制符号链接所指向的文件;如果为 False ,则复制符号链接本身。
                # 异常处理 :
                # shutil.copy2() 可能会抛出异常,如 FileNotFoundError (源文件不存在)、 PermissionError (没有权限写入目标文件)等。因此,在实际使用中,你可能需要捕获这些异常来处理错误情况:
                # shutil.copy2() 是一个非常有用的函数,它在复制文件的同时保留了尽可能多的文件属性,这在需要保持文件完整性的场景中非常有用。
                # shutil.copy2() 是一个方便的工具,用于在需要保留文件元数据的情况下复制文件。与 shutil.copy() 相比, shutil.copy2() 能够更完整地复制文件属性,因此在需要这些属性时应该优先使用 shutil.copy2() 。

                # 使用 shutil.copy2 将文件复制到临时路径,保留元数据(如修改时间等)。
                shutil.copy2(path, tmp_path)

            # 使用 try 块确保在上下文管理器中执行的代码可以正常运行。
            try:
                # Yield the temporary path    输出临时路径。
                # 根据输入路径的类型(字符串或 Path 对象),返回相应的路径。 如果输入是字符串,则返回 临时路径的字符串表示 。 如果输入是 Path 对象,则返回 Path 对象。
                yield str(tmp_path) if string else tmp_path

            # 使用 finally 块确保在退出上下文时执行清理操作,无论是否发生异常。
            finally:
                # Copy file/directory back    复制文件/目录。
                # 如果临时路径是一个目录。
                if tmp_path.is_dir():
                    # 使用 shutil.copytree 将临时目录的内容复制回原始路径,允许覆盖已存在的目录。
                    shutil.copytree(tmp_path, path, dirs_exist_ok=True)
                # 如果临时路径是一个文件。
                elif tmp_path.is_file():
                    # 使用 shutil.copy2 将临时文件复制回原始路径,保留元数据。
                    shutil.copy2(tmp_path, path)  # Copy back the file    复制回文件。

    # 如果路径中没有空格。
    else:
        # If there are no spaces, just yield the original path    如果没有空格,则直接保留原始路径。
        # 直接返回原始路径(无需任何处理)。
        yield path
# spaces_in_path 是一个上下文管理器,用于处理路径中包含空格的情况。它的主要功能包括。临时替换空格:将路径中的空格替换为下划线,避免在某些工具或命令中因空格导致的问题。文件或目录复制:将原始路径的内容复制到临时路径,并在退出上下文时将内容复制回原始路径。类型兼容:根据输入路径的类型(字符串或 Path 对象),返回相应类型的路径。自动清理:在退出上下文时,确保临时目录被清理,原始路径的内容被正确恢复。
# 使用示例 :
# with spaces_in_path("/path/to/my folder") as new_path:
#     print("Temporary path:", new_path)
#     # 在这个上下文内,可以安全地使用 new_path,它不包含空格
#     # 例如,运行某些命令或工具
# # 退出上下文后,原始路径的内容被恢复
# print("Original path restored:", Path("/path/to/my folder").exists())
# 这种上下文管理器非常适用于需要处理路径中空格的场景,例如在调用某些不支持空格路径的命令行工具时。

4.def increment_path(path, exist_ok=False, sep="", mkdir=False): 

# 这段代码定义了一个函数 increment_path ,用于处理文件或目录路径的增量命名,避免路径冲突,并且可以选择是否创建目录。
# 定义了一个函数 increment_path ,接受以下参数 :
# 1.path :目标路径(可以是文件或目录)。
# 2.exist_ok :布尔值,默认为 False 。如果为 False ,当路径已存在时,会尝试生成一个增量路径;如果为 True ,则直接返回原路径。
# 3.sep :字符串,默认为空。用于分隔增量编号和原路径。
# 4.mkdir :布尔值,默认为 False 。如果为 True ,会创建路径对应的目录(如果路径是文件,则创建其父目录)。
def increment_path(path, exist_ok=False, sep="", mkdir=False):
    # 增加文件或目录路径,即 runs/exp --> runs/exp{sep}2、runs/exp{sep}3,... 等等。
    # 如果路径存在且 `exist_ok` 不为 True,则通过在路径末尾附加数字和 `sep` 来增加路径。如果路径是文件,则将保留文件扩展名。如果路径是目录,则数字将直接附加到路径末尾。如果 `mkdir` 设置为 True,则如果路径尚不存在,则将创建为目录。
    # 示例:
    # 增加目录路径:
    # >>> from pathlib import Path
    # >>> path = Path("runs/exp")
    # >>> new_path = increase_path(path)
    # >>> print(new_path)
    # runs/exp2
    # 增加文件路径:
    # >>> path = Path("runs/exp/results.txt")
    # >>> new_path = increase_path(path)
    # >>> print(new_path)
    # runs/exp/results2.txt
    """
    Increments a file or directory path, i.e., runs/exp --> runs/exp{sep}2, runs/exp{sep}3, ... etc.

    If the path exists and `exist_ok` is not True, the path will be incremented by appending a number and `sep` to
    the end of the path. If the path is a file, the file extension will be preserved. If the path is a directory, the
    number will be appended directly to the end of the path. If `mkdir` is set to True, the path will be created as a
    directory if it does not already exist.

    Args:
        path (str | pathlib.Path): Path to increment.
        exist_ok (bool): If True, the path will not be incremented and returned as-is.
        sep (str): Separator to use between the path and the incrementation number.
        mkdir (bool): Create a directory if it does not exist.

    Returns:
        (pathlib.Path): Incremented path.

    Examples:
        Increment a directory path:
        >>> from pathlib import Path
        >>> path = Path("runs/exp")
        >>> new_path = increment_path(path)
        >>> print(new_path)
        runs/exp2

        Increment a file path:
        >>> path = Path("runs/exp/results.txt")
        >>> new_path = increment_path(path)
        >>> print(new_path)
        runs/exp/results2.txt
    """
    # 将输入的 path 转换为 Path 对象,这是一个跨操作系统的路径处理方式,避免了直接使用字符串拼接路径时可能出现的兼容性问题。
    path = Path(path)  # os-agnostic
    #  判断路径是否存在且 exist_ok 是否为 False 。如果路径已存在且不允许覆盖( exist_ok=False ),则进入增量路径生成逻辑。
    if path.exists() and not exist_ok:
        # 如果路径是一个文件,则将路径的扩展名(后缀)分离出来,以便在增量路径中保留扩展名。 path.with_suffix("") 去掉文件的扩展名, path.suffix 获取扩展名。如果路径是一个目录,则 suffix 设置为空字符串。
        path, suffix = (path.with_suffix(""), path.suffix) if path.is_file() else (path, "")

        # Method 1
        # 从 2 开始循环,尝试生成增量路径,直到找到一个不存在的路径为止。循环范围是 2 到 9999,表示最多尝试生成 9998 个增量路径。
        for n in range(2, 9999):
            # 使用格式化字符串生成 增量路径 。 path 是原始路径(去掉扩展名后的部分), sep 是分隔符, n 是增量编号, suffix 是扩展名。
            p = f"{path}{sep}{n}{suffix}"  # increment path
            # 检查生成的增量路径 p 是否不存在。如果不存在,则跳出循环,表示找到了一个可用的路径。
            if not os.path.exists(p):
                break
        # 将找到的可用增量路径 p 转换为 Path 对象,并赋值给变量 path 。
        path = Path(p)

    # 如果参数 mkdir 为 True 。
    if mkdir:
        # 则调用 path.mkdir() 创建路径对应的目录。 parents=True 表示如果需要,会创建所有父目录; exist_ok=True 表示如果目录已存在,不会抛出异常。
        path.mkdir(parents=True, exist_ok=True)  # make directory

    # 返回最终处理后的路径(可能是原始路径、增量路径或已创建的目录路径)。
    return path
# 这段代码实现了一个路径增量命名的功能,主要用于避免文件或目录命名冲突。它通过在路径后添加编号的方式生成新的路径,并且可以根据需要创建目录。通过参数 exist_ok 和 mkdir ,用户可以灵活控制路径的处理方式。

5.def file_age(path=__file__): 

# 这段代码定义了一个函数 file_age ,用于计算指定文件自上次修改以来的天数。
# 定义了一个函数 file_age ,接受一个参数。
# 1.path :默认值为 __file__ (当前脚本文件的路径)。这意味着如果不传入参数,函数将计算当前脚本文件的修改时间。
def file_age(path=__file__):
    # 返回自上次修改指定文件以来的天数。
    """Return days since the last modification of the specified file."""

    # datetime.datetime.fromtimestamp(timestamp[, tz])
    # datetime.fromtimestamp() 是 Python 中 datetime 模块的一个方法,用于根据 Unix 时间戳(自1970年1月1日以来的秒数)来创建一个 datetime 对象。
    # 参数说明 :
    # timestamp : Unix 时间戳,表示自1970年1月1日(UTC)以来的秒数。
    # tz (可选): 时区信息。如果提供,方法将返回指定时区对应的 datetime 对象。如果没有提供时区信息,将使用系统本地时区。
    # 返回值 :
    # 返回一个 datetime 对象,表示给定 Unix 时间戳对应的日期和时间。
    # 注意事项 :
    # datetime.fromtimestamp() 默认返回的是本地时区的时间,如果你需要协调世界时(UTC),可以提供一个时区参数。
    # 如果你在处理时间戳时需要考虑时区,确保正确地使用 tz 参数。
    # 在使用 datetime 模块之前,需要先导入该模块。
    # datetime.fromtimestamp() 是一个非常有用的函数,它允许你将 Unix 时间戳转换为人类可读的日期和时间格式。

    # 获取文件的最后修改时间。
    # Path(path).stat().st_mtime :使用 Path 对象的 stat() 方法获取文件的状态信息, st_mtime 是文件的最后修改时间(以时间戳形式表示)。
    # datetime.fromtimestamp() :将时间戳转换为 datetime 对象。
    # datetime.now() :获取当前时间的 datetime 对象。
    # datetime.now() - datetime.fromtimestamp(...) :计算当前时间与文件最后修改时间的差值,结果是一个 timedelta 对象,存储在变量 dt 中。
    dt = datetime.now() - datetime.fromtimestamp(Path(path).stat().st_mtime)  # delta
    # 返回 timedelta 对象的 days 属性,表示自文件上次修改以来的完整天数。 注释部分 # + dt.seconds / 86400 表示如果需要计算包含小数部分的天数(即包含小时、分钟和秒的部分),可以将 dt.seconds 除以 86400(一天的秒数)并加到 dt.days 上,但这段代码中并未启用。
    return dt.days  # + dt.seconds / 86400  # fractional days
# 这段代码实现了一个简单的功能。计算指定文件自上次修改以来的天数。它通过获取文件的最后修改时间戳,并与当前时间进行比较,最终返回天数差。默认情况下,它计算当前脚本文件的修改时间,但也可以通过传入其他文件路径来计算其他文件的修改时间。

6.def file_date(path=__file__): 

# 这段代码定义了一个函数 file_date ,用于获取指定文件的最后修改日期,并将其格式化为 'YYYY-M-D' 格式。
# 定义了一个函数 file_date ,接受一个参数。
# 1.path :默认值为 __file__ (当前脚本文件的路径)。这意味着如果不传入参数,函数将获取当前脚本文件的修改日期。
def file_date(path=__file__):
    # 以“YYYY-M-D”格式返回文件修改日期。
    """Returns the file modification date in 'YYYY-M-D' format."""
    # 获取文件的最后修改时间。
    # Path(path).stat().st_mtime :使用 Path 对象的 stat() 方法获取文件的状态信息, st_mtime 是文件的最后修改时间(以时间戳形式表示)。
    # datetime.fromtimestamp() :将时间戳转换为 datetime 对象,并将其存储在变量 t 中。
    t = datetime.fromtimestamp(Path(path).stat().st_mtime)
    # 使用格式化字符串将 datetime 对象 t 的年、月、日部分提取出来,并按照 'YYYY-M-D' 的格式拼接成字符串返回。例如,如果文件的最后修改时间是 2025年2月7日 ,则返回的字符串为 '2025-2-7' 。
    return f"{t.year}-{t.month}-{t.day}"
# 这段代码实现了一个简单的功能。获取指定文件的最后修改日期,并将其格式化为 'YYYY-M-D' 格式。它通过获取文件的最后修改时间戳,并将其转换为 datetime 对象,最后提取年、月、日并拼接成字符串返回。默认情况下,它获取当前脚本文件的修改日期,但也可以通过传入其他文件路径来获取其他文件的修改日期。

7.def file_size(path): 

# 这段代码定义了一个函数 file_size ,用于计算文件或目录的大小,并以兆字节(MB)为单位返回结果。
# 定义了一个函数 file_size ,接受一个参数。
# 1.path :该参数可以是字符串或 Path 对象,表示文件或目录的路径。
def file_size(path):
    # 以兆字节 (MB) 为单位返回文件或目录的大小。
    """Returns the size of a file or directory in megabytes (MB)."""
    # 检查输入的 path 是否为字符串或 Path 对象。如果不是,函数将直接返回 0.0 。
    if isinstance(path, (str, Path)):
        # 定义一个变量 mb ,表示 1 兆字节(MiB)的字节数。 1 << 20 是通过位移操作计算出 1024 ** 2 (即 1048576),这是从字节(bytes)到兆字节(MiB)的换算系数。
        mb = 1 << 20  # bytes to MiB (1024 ** 2)
        # 将输入的 path 转换为 Path 对象,以便后续操作。
        path = Path(path)
        # 检查 path 是否是一个文件。如果是文件,进入以下逻辑。
        if path.is_file():
            # 使用 path.stat().st_size 获取文件的大小(以字节为单位),然后除以 mb (1048576),将结果转换为兆字节(MiB)并返回。
            return path.stat().st_size / mb
        # 如果 path 不是一个文件,则检查是否是一个目录。如果是目录,进入以下逻辑。
        elif path.is_dir():
            # 使用 path.glob("**/*") 遍历目录及其所有子目录中的所有文件( **/* 表示递归匹配所有文件和目录)。
            # 使用列表推导式 f.stat().st_size for f in path.glob("**/*") if f.is_file() 获取每个文件的大小(以字节为单位),并使用 sum() 函数计算总大小。
            # 最后,将总大小除以 mb ,将结果转换为兆字节(MiB)并返回。
            return sum(f.stat().st_size for f in path.glob("**/*") if f.is_file()) / mb
    # 如果输入的 path 既不是字符串也不是 Path 对象,或者路径无效(既不是文件也不是目录),则返回 0.0 。
    return 0.0
# 这段代码实现了一个功能。计算文件或目录的大小,并以兆字节(MB)为单位返回结果。它通过以下逻辑实现。检查输入路径是否有效(字符串或 Path 对象)。如果路径是文件,直接获取文件大小并转换为 MB。如果路径是目录,递归遍历目录中的所有文件,计算总大小并转换为 MB。如果路径无效或既不是文件也不是目录,返回 0.0 。这种实现方式既支持单个文件的大小计算,也支持整个目录的大小计算,具有较高的通用性。

8.def get_latest_run(search_dir="."): 

# 这段代码定义了一个函数 get_latest_run ,用于在指定目录中查找最新的 last.pt 文件,通常用于恢复训练模型。
# 定义了一个函数 get_latest_run ,接受一个参数。
# 1.search_dir :默认值为 "." ,表示当前工作目录。该参数指定了要搜索的目录。
def get_latest_run(search_dir="."):
    # 返回指定目录中最新的“last.pt”文件的路径,以恢复训练。
    """Returns the path to the most recent 'last.pt' file in the specified directory for resuming training."""
    # 使用 glob.glob 函数搜索指定目录及其所有子目录( recursive=True )中所有匹配 last*.pt 的文件路径。
    # search_dir 是搜索的根目录。
    # /**/last*.pt 是搜索模式,表示在所有子目录中查找以 last 开头且以 .pt 结尾的文件。
    # 结果存储在变量 last_list 中,它是一个 包含所有匹配文件路径的列表 。
    last_list = glob.glob(f"{search_dir}/**/last*.pt", recursive=True)
    # 如果 last_list 不为空(即找到了匹配的文件),使用 max 函数找到其中“最新”的文件。
    # key=os.path.getctime :指定 max 函数的比较标准为文件的创建时间( getctime )。
    # max(last_list, key=os.path.getctime) :返回列表中创建时间最新的文件路径。
    # 如果 last_list 为空(即没有找到匹配的文件),返回空字符串 "" 。
    return max(last_list, key=os.path.getctime) if last_list else ""
# 这段代码实现了一个功能。在指定目录及其子目录中查找最新的 last.pt 文件,通常用于恢复训练模型。它通过以下逻辑实现。使用 glob.glob 在指定目录及其子目录中搜索所有匹配 last*.pt 的文件。如果找到文件,通过文件的创建时间找到最新的文件。如果没有找到文件,返回空字符串。这种实现方式简单高效,适用于需要恢复训练模型的场景,例如在深度学习项目中。

9.def update_models(model_names=("yolo11n.pt",), source_dir=Path("."), update_names=False): 

# 这段代码定义了一个函数 update_models ,用于更新指定模型文件,并将其保存到目标目录中。
# 定义了一个函数 update_models ,接受以下参数 :
# 1.model_names :一个元组,默认值为 ("yolo11n.pt",) ,包含需要更新的模型文件名。
# 2.source_dir :一个 Path 对象,默认值为当前目录( Path(".") ),表示模型文件所在的源目录。
# 3.update_names :一个布尔值,默认值为 False ,表示是否更新模型的类别名称。
def update_models(model_names=("yolo11n.pt",), source_dir=Path("."), update_names=False):
    # 更新并重新保存“updated_models”子目录中的指定 YOLO 模型。
    """
    Updates and re-saves specified YOLO models in an 'updated_models' subdirectory.

    Args:
        model_names (Tuple[str, ...]): Model filenames to update.
        source_dir (Path): Directory containing models and target subdirectory.
        update_names (bool): Update model names from a data YAML.

    Examples:
        Update specified YOLO models and save them in 'updated_models' subdirectory:
        >>> from ultralytics.utils.files import update_models
        >>> model_names = ("yolo11n.pt", "yolov8s.pt")
        >>> update_models(model_names, source_dir=Path("/models"), update_names=True)
    """
    # 导入了 YOLO 类和 default_class_names 函数,这些是用于加载和更新模型的工具。
    from ultralytics import YOLO
    from ultralytics.nn.autobackend import default_class_names

    # 定义目标目录路径,位于 source_dir 下的 updated_models 文件夹。
    target_dir = source_dir / "updated_models"
    # 使用 mkdir 方法创建目标目录, parents=True 表示如果需要,会创建所有父目录; exist_ok=True 表示如果目录已存在,不会抛出异常。
    target_dir.mkdir(parents=True, exist_ok=True)  # Ensure target directory exists

    # 遍历 model_names 中的每个模型文件名。
    for model_name in model_names:
        # 构造模型文件的完整路径,位于 source_dir 下。
        model_path = source_dir / model_name
        # 打印正在加载的模型路径,用于提示用户。
        print(f"Loading model from {model_path}")    # 从 {model_path} 加载模型。

        # Load model
        # 使用 YOLO 类加载模型文件。
        model = YOLO(model_path)
        # 将模型转换为半精度(16位浮点数)格式,通常用于加速推理并减少模型大小。
        model.half()
        # 如果 update_names 为 True 。
        if update_names:  # update model names from a dataset YAML
            # 则更新模型的类别名称。这里使用 default_class_names("coco8.yaml") 从 coco8.yaml 文件中获取类别名称,并将其赋值给模型的 names 属性。
            # def default_class_names(data=None):
            # -> 用于从输入的 YAML 文件中提取类别名称,或者在无法提取时返回默认的类别名称。提取 names 字段,返回类别名称列表。如果无法从输入数据中提取类别名称(或未提供输入),则返回默认的类别名称字典。
            # -> return yaml_load(check_yaml(data))["names"] / return {i: f"class{i}" for i in range(999)}  # return default if above errors
            model.model.names = default_class_names("coco8.yaml")

        # Define new save path
        # 定义 保存更新后模型的目标路径 ,位于 target_dir 下。
        save_path = target_dir / model_name

        # Save model using model.save()
        # 打印正在保存的模型路径,用于提示用户。
        print(f"Re-saving {model_name} model to {save_path}")    # 将 {model_name} 模型重新保存至 {save_path}。
        # 使用 model.save() 方法将更新后的模型保存到目标路径。
        model.save(save_path)
# 这段代码实现了一个功能。更新指定的 YOLO 模型文件,并将其保存到目标目录中。它通过以下逻辑实现。创建目标目录,用于存放更新后的模型。遍历指定的模型文件名,加载每个模型。将模型转换为半精度格式。如果需要,更新模型的类别名称。将更新后的模型保存到目标目录。这种实现方式适用于需要批量更新模型文件的场景,例如在深度学习项目中对模型进行优化或更新类别名称。


http://www.niftyadmin.cn/n/5845175.html

相关文章

问题大集04-浏览器阻止从 本地 发起的跨域请求,因为服务器的响应头 Access-Control-Allow-Origin 设置为通配符 *

1、问题 localhost/:1 Access to XMLHttpRequest at xxx&#xff08;请求&#xff09; from origin http://localhost:xxx&#xff08;本地&#xff09; has been blocked by CORS policy: The value of the Access-Control-Allow-Origin header in the response must not be t…

WPF 进度条(ProgressBar)示例一

本文讲述&#xff1a;WPF 进度条(ProgressBar)简单的样式修改和使用。 进度显示界面&#xff1a;使用UserControl把ProgressBar和进度值以及要显示的内容全部组装在UserControl界面中&#xff0c;方便其他界面直接进行使用。 <UserControl x:Class"DefProcessBarDemo…

代码随想录 Day 16 | 【第六章 二叉树】找树左下角的值、路径总和、从中序与后序遍历序列构造二叉树

一、513.找树左下角的值 本题递归偏难&#xff0c;反而迭代简单属于模板题&#xff0c; 两种方法掌握一下 题目链接/文章讲解/视频讲解&#xff1a;代码随想录 1. 整体思路 本题要求找出该二叉树的 最底层 最左边 节点的值。需要注意的是&#xff1a; 1&#xff09;最底层&…

【Flink源码分析】3. Flink1.19源码分析-精通动态代理

3.1 Java 动态代理 动态代理是一种设计模式&#xff0c;它允许在运行时创建代理对象&#xff0c;并将方法调用重定向到不同的实际对象。它使我们能够在不修改现有代码的情况下增加或改变某个对象的行为。 3.1.1 InvocationHandler接口&#xff1a; 这个接口定义了一个invoke…

【LeetCode-27】移除元素

目录 一、算法&#xff1a;移除元素问题 二、题目描述 三、相关知识 数组 &#xff08;1&#xff09;数组的特点 &#xff08;2&#xff09;数组的操作 时间复杂度与空间复杂度 &#xff08;1&#xff09;时间复杂度 &#xff08;2&#xff09;空间复杂度 &#xff0…

【论文阅读】Comment on the Security of “VOSA“

Comment on the Security of Verifiable and Oblivious Secure Aggregation for Privacy-Preserving Federated Learning -- 关于隐私保护联邦中可验证与遗忘的安全聚合的安全性 论文来源摘要Introduction回顾 VOSA 方案对VOSA不可伪造性的攻击对于类型 I 的攻击对于类型 II 的…

doris:MySQL 兼容性

Doris 高度兼容 MySQL 语法&#xff0c;支持标准 SQL。但是 Doris 与 MySQL 还是有很多不同的地方&#xff0c;下面给出了它们的差异点介绍。 数据类型​ 数字类型​ 类型MySQLDorisBoolean- 支持 - 范围&#xff1a;0 代表 false&#xff0c;1 代表 true- 支持 - 关键字&am…

计算机网络-SSH基本原理

最近年底都在忙&#xff0c;然后这两天好点抽空更新一下。前面基本把常见的VPN都学习了一遍&#xff0c;后面的内容应该又继续深入一点。 一、SSH简介 SSH&#xff08;Secure Shell&#xff0c;安全外壳协议&#xff09;是一种用于在不安全网络上进行安全远程登录和实现其他安…