当前位置: 首页 > article >正文

YOLOv8-ultralytics-8.2.103部分代码阅读笔记-files.py

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=("yolov8n.pt",), source_dir=Path("."), update_names=False): 


1.所需的库和模块

# Ultralytics YOLO 🚀, AGPL-3.0 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 ,使其可以被用作词法装饰器或上下文管理器。
# 类定义。
# WorkingDirectory :类名。 contextlib.ContextDecorator :父类,提供了上下文管理器的基础实现。
class WorkingDirectory(contextlib.ContextDecorator):
    # 用于临时更改工作目录的上下文管理器和装饰器。
    # 此类允许使用上下文管理器或装饰器临时更改工作目录。
    # 它确保在上下文或装饰函数完成后恢复原始工作目录。
    # 方法:
    # __enter__ :将当前目录更改为指定目录。
    # __exit__ :在退出上下文时恢复原始工作目录。
    """
    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."""
        # 属性初始化。
        # 保存新目录的路径。
        self.dir = new_dir  # new dir

        # current_working_directory = Path.cwd()
        # 在Python中, cwd() 函数是 pathlib 模块中的一个方法,用于获取当前工作目录。这个方法是 Path 类的一个实例方法, Path 类是 pathlib 模块中用于处理文件系统路径的类。
        # 功能描述 :
        # Path.cwd() 方法返回一个 Path 对象,该对象代表当前工作目录的路径。
        # 返回值 :
        # Path.cwd() 方法返回的是 Path 对象,这个对象提供了许多方法来操作路径,例如 .resolve() 可以获取路径的绝对路径, .as_posix() 可以将路径转换为跨平台的字符串形式等。
        # 异常处理 :
        # Path.cwd() 方法通常不会抛出异常,因为它只是返回当前工作目录的路径。但是,如果系统出现问题,导致无法确定当前工作目录,可能会抛出异常,这种情况下应该进行异常处理。

        # 保存当前工作目录的路径,并使用 Path.cwd().resolve() 来获取绝对路径。
        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 指定的目录。
        os.chdir(self.dir)

    # 退出上下文 __exit__ 。这个方法在退出上下文管理器时被调用。
    # 1.exc_type 、 2.exc_val 和 3.exc_tb 是异常相关的参数,分别代表 异常类型 、 异常值 和 异常的traceback 。
    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)
# 使用这个类,你可以在代码块中临时更改工作目录,而不影响外部目录。

3.def spaces_in_path(path): 

# 这段代码定义了一个名为 spaces_in_path 的上下文管理器,它使用 contextmanager 装饰器来自 contextlib 模块。这个上下文管理器的目的是处理包含空格的文件路径,通过将空格替换为下划线,并在临时目录中复制文件或目录来避免路径中空格可能引起的问题。
# 上下文管理器定义。
# @contextmanager 装饰器,用于定义一个上下文管理器。
# spaces_in_path 函数名,接受一个参数。
# 1.path :表示可能包含空格的文件路径。
@contextmanager
def spaces_in_path(path):
    # 上下文管理器处理名称中带有空格的路径。如果路径包含空格,它会用下划线替换它们,将文件/目录复制到新路径,执行上下文代码块,然后将文件/目录复制回其原始位置。
    # Yields:
    # (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 是否为字符串类型,以便在上下文管理器的 yield 语句后返回相同类型的路径。
        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() 创建一个临时目录。
        with tempfile.TemporaryDirectory() as tmp_dir:
            # 构造一个新的路径 tmp_path ,将原始路径中的文件名中的空格替换为下划线。
            tmp_path = Path(tmp_dir) / path.name.replace(" ", "_")

            # Copy file/directory
            # 复制文件或目录。
            # 如果 path 是目录,使用 shutil.copytree() 复制整个目录到临时路径。
            if path.is_dir():

                # 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() 是一个强大的工具,用于复制整个目录树,常用于备份、同步文件或在测试中创建测试数据目录。

                # tmp_path.mkdir(parents=True, exist_ok=True)
                shutil.copytree(path, tmp_path)
            # 如果 path 是文件,使用 shutil.copy2() 复制文件到临时路径。
            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(path, tmp_path)

            try:
                # Yield the temporary path
                # 提供临时路径。 yield 语句提供临时路径,如果原始 path 是字符串类型,则返回字符串类型的临时路径,否则返回 Path 对象。
                yield str(tmp_path) if string else tmp_path

            # 将文件或目录复制回原始位置。在 finally 块中,确保无论上下文代码块中发生什么,都会将临时目录中的文件或目录复制回原始位置。
            finally:
                # Copy file/directory back
                if tmp_path.is_dir():
                    shutil.copytree(tmp_path, path, dirs_exist_ok=True)
                elif tmp_path.is_file():
                    shutil.copy2(tmp_path, path)  # Copy back the file

    # 处理路径中不包含空格的情况。如果路径中不包含空格,则直接 yield 原始路径。
    else:
        # If there are no spaces, just yield the original path
        yield path
# 使用这个上下文管理器,你可以确保在代码块中处理的路径不包含空格,从而避免某些操作系统或程序中可能由于路径中的空格引起的问题。

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

# 这段代码定义了一个名为 increment_path 的函数,其目的是在给定路径已存在的情况下,通过在路径后面添加一个数字后缀来生成一个新的路径,直到找到一个不存在的路径。这个函数可以用来避免文件或目录的覆盖。
# 函数定义。
# 1.path :要检查和增加后缀的文件或目录的路径。
# 2.exist_ok :一个布尔值,如果为 True ,则即使原始路径已存在也不会增加后缀。
# 3.sep :后缀数字前的分隔符,默认为空字符串。
# 4.mkdir :一个布尔值,如果为 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,则如果路径尚不存在,则将创建为目录。
    """
    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 ,则需要增加后缀。
    if path.exists() and not exist_ok:
        # 如果 path 是文件,则保存其后缀名,并移除后缀名以便添加数字后缀;如果 path 是目录,则保持不变。
        path, suffix = (path.with_suffix(""), path.suffix) if path.is_file() else (path, "")

        # Method 1
        # 使用 range(2, 9999) 来生成数字后缀,从2开始以避免覆盖原始文件,并检查新路径是否存在。如果找到了一个不存在的路径,则退出循环。
        for n in range(2, 9999):
            p = f"{path}{sep}{n}{suffix}"  # increment path
            if not os.path.exists(p):
                break
        path = Path(p)

    # 如果 mkdir 参数为 True ,则创建新的目录路径, parents=True 允许创建多级目录, exist_ok=True 忽略目录已存在的错误。
    if mkdir:

        # os.mkdir(path, mode=0o777, *, dir_fd=None, parents=False, exist_ok=False)
        # 在Python中, mkdir() 函数是 os 模块中的一个函数,用于创建一个新目录。
        # 参数说明 :
        # path : 要创建的目录路径。
        # mode : 可选参数,用于设置目录的权限模式,默认为 0o777 。在Unix和类Unix系统中有效。
        # dir_fd : 可选参数,文件描述符;如果提供,表示 path 是相对于此文件描述符的。
        # parents : 可选参数,布尔值;如果为 True ,则会创建父目录。
        # exist_ok : 可选参数,布尔值;如果为 True ,当目录已存在时不会抛出异常。
        # 注意事项 :
        # 如果 parents=True , mkdir() 会递归地创建所有必需的父目录。
        # 如果 exist_ok=True ,当目录已存在时, mkdir() 不会抛出 FileExistsError 异常。
        # 在使用 mkdir() 时,需要确保程序有足够的权限来创建目录。
        # 这个函数是处理文件系统操作的常用工具,可以帮助你管理目录结构。

        path.mkdir(parents=True, exist_ok=True)  # make directory

    # 返回最终的路径,可能是原始路径(如果 exist_ok 为 True 且路径不存在),或者是一个增加了数字后缀的新路径。
    return path
# 这个函数在处理文件和目录的创建时非常有用,特别是在需要确保不覆盖现有文件或目录的情况下。通过自动增加后缀,它可以确保新创建的文件或目录总是唯一的。

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.now([tz])
    # datetime.now() 是 Python 中 datetime 模块的一个方法,用于获取当前的日期和时间。
    # 参数说明 :
    # tz (可选): 时区信息。如果提供, now() 方法将返回指定时区的当前时间。如果没有提供时区信息,将使用系统本地时区。
    # 返回值 :
    # 返回一个 datetime 对象,表示当前的日期和时间。
    # 注意事项 :
    # datetime.now() 返回的是本地时区的时间,如果你需要协调世界时(UTC),可以使用 datetime.utcnow() 方法。
    # 如果你需要更精确的时间(包括微秒),可以使用 datetime.now(timezone.utc) 来获取。
    # 在使用 datetime 模块之前,需要先导入该模块。
    # datetime.now() 是处理日期和时间的常用方法,可以帮助你获取当前的日期和时间。

    # 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 时间戳转换为人类可读的日期和时间格式。

    # os.stat(path, *, dir_fd=None, follow_symlinks=True, dir_fd=None)
    # 在Python中, stat() 函数是 os 模块中的一个方法,用于获取文件或目录的状态信息。
    # 参数说明 :
    # path : 要获取状态信息的文件或目录的路径。
    # dir_fd : 可选参数,文件描述符;如果提供,表示 path 是相对于此文件描述符的。
    # follow_symlinks : 可选参数,布尔值;如果为 True (默认值),则 stat() 会跟随软链接,并返回链接目标的状态信息;如果为 False ,则返回链接本身的状态信息。
    # 返回值 :
    # 返回一个对象,该对象包含了文件或目录的许多属性,如修改时间、访问时间、文件大小等。
    # 返回对象的属性 :
    # 返回的对象包含以下属性(这些属性在不同的操作系统中可能有所不同) :
    # st_mode : 文件模式(类型与权限)。
    # st_ino : inode(节点)编号。
    # st_dev : 设备编号。
    # st_nlink : 硬链接数。
    # st_uid : 文件所有者的ID。
    # st_gid : 文件所有者组的ID。
    # st_size : 文件大小,单位为字节。
    # st_atime : 最后访问时间,以Unix时间戳表示。
    # st_mtime : 最后修改时间,以Unix时间戳表示。
    # st_ctime : 最后状态改变时间(inode修改时间),以Unix时间戳表示。
    # 注意事项 :
    # 使用 stat() 函数时,需要确保提供的路径是存在的,否则会抛出 FileNotFoundError 。
    # stat() 函数返回的属性在不同的操作系统中可能有所不同,因此在编写跨平台代码时需要注意这一点。
    # 在使用 os 模块之前,需要先导入该模块。
    # stat() 函数是处理文件系统操作时常用的一个函数,它提供了获取文件或目录状态信息的直接方法。

    # datetime.now() 获取当前的日期和时间。
    # datetime.fromtimestamp(Path(path).stat().st_mtime) 将文件的最后修改时间(以时间戳形式)转换为 datetime 对象。
    # Path(path) 是从 pathlib 模块创建的 Path 对象, stat() 方法获取文件的状态信息, st_mtime 是文件最后修改的时间戳。
    # 两个 datetime 对象相减得到一个 timedelta 对象,表示两个时间点之间的差异。
    dt = datetime.now() - datetime.fromtimestamp(Path(path).stat().st_mtime)  # delta
    # 返回 timedelta 对象中的天数部分。 注释掉的 + dt.seconds / 86400 部分如果取消注释,将会计算天数的小数部分,即包括小时、分钟和秒在内的完整天数。
    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) 是从 pathlib 模块创建的 Path 对象,它提供了面向对象的文件系统路径操作方法。
    # Path(path).stat() 获取文件的状态信息,类似于 os.stat(path) 。
    # st_mtime 是文件最后修改的时间戳, datetime.fromtimestamp() 方法将这个时间戳转换成 datetime 对象。
    t = datetime.fromtimestamp(Path(path).stat().st_mtime)
    # t.year 、 t.month 和 t.day 分别获取 datetime 对象的年、月、日。 使用 f-string(格式化字符串字面量)来格式化返回的日期字符串为 'YYYY-M-D' 格式。
    return f"{t.year}-{t.month}-{t.day}"
# 函数中的 Path(path).stat().st_mtime 需要确保 path 是一个有效的文件路径,否则会抛出异常。返回的日期格式是固定的 'YYYY-M-D' ,如果你需要其他格式,可以修改 f-string 来适应你的需求。
# 这个函数可以很方便地用于获取文件的最后修改日期,并以一种简洁的格式返回。

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 对象。
    if isinstance(path, (str, Path)):
        # 定义了从字节到兆字节(MiB)的转换因子,因为1兆字节等于 2^20 字节。
        mb = 1 << 20  # bytes to MiB (1024 ** 2)
        # 将路径转换为 Path 对象,以便使用 pathlib 模块的方法。
        path = Path(path)
        # 检查路径是否指向一个文件。
        if path.is_file():
            # 如果是文件, path.stat().st_size 获取文件的大小(以字节为单位),然后除以 mb 转换为兆字节,并返回这个值。
            return path.stat().st_size / mb
        # 检查路径是否指向一个目录。
        elif path.is_dir():
            # 如果是目录, path.glob("**/*") 会递归地获取目录下所有文件的路径。
            # sum(f.stat().st_size for f in path.glob("**/*") if f.is_file()) 计算所有文件的大小总和(以字节为单位)。
            # 总大小除以 mb 转换为兆字节,并返回这个值。
            return sum(f.stat().st_size for f in path.glob("**/*") if f.is_file()) / mb
    # 如果路径既不是文件也不是目录,函数返回0.0。
    return 0.0
# 函数中的 path.is_file() 和 path.is_dir() 方法需要确保 path 是一个有效的文件或目录路径,否则会抛出异常。函数中的 glob("**/*") 方法会递归地搜索目录下的所有文件,这可能在包含大量文件的目录中导致性能问题。
# 这个函数可以很方便地用于获取文件或目录的大小,并以兆字节为单位返回。

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 函数搜索 search_dir 目录及其所有子目录中匹配模式 last*.pt 的文件。 recursive=True 参数使得搜索是递归的,即包括所有子目录。
    last_list = glob.glob(f"{search_dir}/**/last*.pt", recursive=True)
    # max(last_list, key=os.path.getctime) 如果 last_list 不为空,使用 max 函数找到列表中创建时间(ctime)最新的文件路径。 key=os.path.getctime 指定 max 函数使用每个文件的创建时间作为比较的键。
    # if last_list else "" 如果 last_list 为空(即没有找到任何文件),函数返回一个空字符串。
    return max(last_list, key=os.path.getctime) if last_list else ""
# 函数中的 glob.glob 方法会搜索所有匹配的文件,如果目录中有很多文件,这可能会影响性能。 os.path.getctime 返回的是文件的创建时间,在某些操作系统上,这可能与文件的实际创建时间不同,或者在文件被修改后可能会改变。
# 这个函数可以很方便地用于在目录中查找最新的 last.pt 文件,以便恢复训练。

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

# 这段代码定义了一个名为 update_models 的函数,它用于更新指定模型列表中的模型,并将它们保存到目标目录。
# 函数定义。update_models 是函数名。
# 1.model_names :是函数的参数,默认值为 ("yolov8n.pt",) ,表示要更新的模型文件名列表。
# 2.source_dir :是函数的参数,默认值为 Path(".") ,表示模型文件所在的源目录。
# 3.update_names :是函数的参数,默认值为 False ,表示是否更新模型中使用的类别名称。
def update_models(model_names=("yolov8n.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 = ("yolov8n.pt", "yolov8s.pt")
        >>> update_models(model_names, source_dir=Path("/models"), update_names=True)
    """
    # 导入模块。
    # 导入 ultralytics 库中的 YOLO 类,用于加载和保存 YOLO 模型。
    from ultralytics import YOLO
    # 导入 default_class_names 函数,用于获取默认的类别名称。
    from ultralytics.nn.autobackend import default_class_names

    # 定义目标目录 target_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:
        # 构造每个模型文件的完整路径 model_path 。
        model_path = source_dir / model_name
        # 打印正在加载的模型路径。
        print(f"Loading model from {model_path}")    # 从 {model_path} 加载模型。

        # Load model
        # 使用 YOLO 类加载模型。
        model = YOLO(model_path)
        # 调用 model.half() 方法将模型转换为半精度(FP16),以减少模型大小并可能加快推理速度。
        model.half()
        # 如果 update_names 参数为 True ,则更新模型中的类别名称为 coco8.yaml 文件中定义的默认类别名称。
        if update_names:  # update model names from a dataset YAML
            # def default_class_names(data=None):
            # -> 从一个输入的 YAML 文件中加载默认的类别名称,或者在加载过程中出现错误时返回一组默认的数值类别名称。返回值。函数返回一个包含类别名称的字典。如果成功加载了 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
        # 定义新的保存路径 save_path ,它是目标目录下的模型文件名。
        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() 方法保存模型到新路径, use_dill=False 表示不使用 dill 序列化库。
        model.save(save_path, use_dill=False)
# 这个函数依赖于 ultralytics 库,所以在使用之前需要确保该库已正确安装。
# default_class_names 函数需要一个 YAML 文件路径作为参数,该文件应包含类别名称的定义。
# 函数中的 model.save() 方法需要 ultralytics 库支持的模型对象。
# 确保源目录和目标目录的路径正确,且有足够的权限进行文件操作。这个函数可以很方便地用于批量更新和保存 YOLO 模型,特别是当需要更新模型的类别名称或将模型转换为半精度时。


http://www.kler.cn/a/418343.html

相关文章:

  • 【目标检测】YOLO:深度挖掘YOLO的性能指标。
  • [CTF/网络安全] 攻防世界 upload1 解题详析
  • FPGA存在的意义:为什么adc连续采样需要fpga来做,而不会直接用iic来实现
  • 积鼎科技携手西北工业大学动力与能源学院共建复杂多相流仿真联合实验室
  • 简单的Activiti Modoler 流程在线编辑器
  • 循环神经网络(RNN)简述
  • LSTM神经网络时间序列
  • 使用Docker在Ubuntu 22.04上部署MySQL数据库的完整指南
  • 如何在 VPS 上设置 Apache 并使用免费签名的 SSL 证书
  • Uniapp 使用自定义字体
  • Linux下如何安装JDK
  • 粒子群算法优化RBF网络
  • spark同步mysql数据到sqlserver
  • Latex相关问题
  • 基于yolov8、yolov5的铝材缺陷检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
  • 强国复兴项目携手易方达基金、广发基金 高效推进扶贫金发放与保障房建设
  • windows C#-相等比较
  • 《windows堆内存剖析(一)》
  • ChromeBook11 HP G7EE 刷入Ubuntu的记录
  • 鲲鹏麒麟安装离线版MySQL5.7
  • 吉客云数据集成技巧:智能实现MySQL物料信息查询
  • 栈-数组描述(C++)
  • mysql查询语句执行全流程
  • 10x 性能提升,ProtonBase 为教育行业提供统一的数据库和数仓体验
  • 【C#设计模式(16)——解释器模式(Interpreter Pattern)】
  • 搭建业务的性能优化指南