YOLOv9-0.1部分代码阅读笔记-__init__.py

发布于:2024-12-18 ⋅ 阅读:(37) ⋅ 点赞:(0)

__init__.py

utils\__init__.py

目录

__init__.py

1.所需的库和模块

2.def emojis(str=''): 

3.class TryExcept(contextlib.ContextDecorator): 

4.def threaded(func): 

5.def join_threads(verbose=False): 

6.def notebook_init(verbose=True): 


1.所需的库和模块

import contextlib
import platform
import threading

2.def emojis(str=''): 

# 这段代码定义了一个名为 emojis 的函数,其目的是返回一个在特定平台(特别是Windows)上安全的、不包含emoji的字符串版本。
# 这行定义了一个名为 emojis 的函数,它接受一个参数.
# 1.str :这个参数默认值为一个空字符串 '' 。这意味着如果你调用这个函数而不传递任何参数, str 将默认为一个空字符串。
def emojis(str=''):
    # Return platform-dependent emoji-safe version of string
    # 这行是函数的主体,它包含了一个条件表达式(也称为三元运算符)。
    # platform.system() :是一个函数调用,它返回当前操作系统的名称。如果这个名称是 'Windows' ,那么条件为真。
    # 如果条件为真(即在Windows系统上),则执行 str.encode().decode('ascii', 'ignore') :
    # str.encode() :将字符串编码为字节串。默认情况下,这会使用字符串的编码(在大多数情况下是UTF-8)。
    # .decode('ascii', 'ignore') :将字节串解码回字符串,但只使用ASCII编码。这意味着任何非ASCII字符(包括emoji)都会被忽略,因为它们不能被ASCII编码表示。 'ignore' 参数告诉解码器忽略这些字符,而不是抛出错误。
    # 如果条件为假(即不在Windows系统上),则直接返回原始的 str 参数。
    return str.encode().decode('ascii', 'ignore') if platform.system() == 'Windows' else str
# 这个函数的目的是确保在Windows系统上,任何包含emoji或其他非ASCII字符的字符串在处理时不会引发错误,方法是将这些字符忽略掉。在非Windows系统上,字符串则原样返回,因为这些系统通常对emoji有更好的支持。

3.class TryExcept(contextlib.ContextDecorator): 

# 这段代码定义了一个名为 TryExcept 的上下文管理器类,它继承自 contextlib.ContextDecorator 。这个上下文管理器的作用是在代码块执行过程中捕获异常,并在异常发生时打印一条包含自定义消息和异常值的消息。
class TryExcept(contextlib.ContextDecorator):
    # YOLOv5 TryExcept class. Usage: @TryExcept() decorator or 'with TryExcept():' context manager
    # 构造函数。 __init__   方法接受一个可选参数。
    # 1.msg :用于在异常发生时显示自定义消息。
    def __init__(self, msg=''):
        self.msg = msg

    # 上下文管理器方法。
    # __enter__ 方法在进入上下文管理器时被调用,这里没有执行任何操作。
    def __enter__(self):
        pass

    #  __exit__ 方法在退出上下文管理器时被调用,它接收三个参数。
    # 1.exc_type :异常类型。
    # 2.value :异常值。
    # 3.traceback : traceback 对象。
    def __exit__(self, exc_type, value, traceback):
        # 如果 value 不为 None (即发生了异常),则打印自定义消息和异常信息。
        if value:
            # emojis 函数被用来格式化输出消息,这个函数用于在消息中添加表情符号。
            print(emojis(f"{self.msg}{': ' if self.msg else ''}{value}"))
        # 方法返回 True ,表示异常已经被处理,不需要进一步传播。
        return True

4.def threaded(func): 

# 这段代码定义了一个名为 threaded 的装饰器,它用于将一个函数转换为多线程执行。
# 定义一个装饰器函数 threaded ,它接受一个函数 1.func 作为参数。
def threaded(func):
    # Multi-threads a target function and returns thread. Usage: @threaded decorator    对目标函数进行多线程处理并返回线程。用法:@threaded 装饰器。
    # 在 threaded 函数内部定义一个 wrapper 函数,这个函数将接受任意数量的位置参数 *args 和关键字参数 **kwargs ,这样它就可以接受任何参数并传递给被装饰的函数。
    def wrapper(*args, **kwargs):

        # threading.Thread(group=None, target=None, name=None, args=(), kwargs=None, daemon=None)
        # threading.Thread() 是 Python 标准库 threading 模块中的一个函数,用于创建一个新的线程对象。
        # 参数 :
        # group : 线程组对象,用于标识线程所属的组。在 Python 中,这个参数通常被设置为 None 。
        # target : 线程启动后要执行的目标函数或方法。
        # name : 线程的名称。如果未指定,则线程会有一个默认名称。
        # args : 传递给 target 函数的位置参数元组。默认为空元组 () 。
        # kwargs : 传递给 target 函数的关键字参数字典。默认为 None 。
        # daemon : 布尔值,表示线程是否为守护线程。如果为 True ,则主程序退出时,线程也会自动退出。默认为 None ,在 Python 的某些版本中,这意味着线程不是守护线程,除非 target 参数为 None 。
        # 返回值 :
        # 返回一个 Thread 对象。
        # 功能描述 :
        # 这个函数创建并返回一个新线程对象。线程对象创建后,需要调用其 start() 方法来启动线程。线程启动后,会执行 target 参数指定的函数,并将 args 和 kwargs 传递给它。
        # 使用场景 :
        # 当需要并行执行多个任务时。
        # 当需要在后台执行某些操作而不阻塞主线程时。
        # 注意事项 :
        # 线程的创建和销毁都有一定的开销,因此不应该频繁地创建和销毁线程。
        # 线程之间共享全局解释器锁(GIL),在 Python 中,GIL 意味着同一时刻只有一个线程可以执行 Python 字节码。
        # 确保线程安全,避免多个线程访问共享资源时发生竞态条件。
        # Thread 对象是 Python threading 模块中用于创建和管理线程的类。以下是一些常用的属性和方法 :
        # 属性 :
        # name : 线程的名称。如果创建时没有指定,会自动生成一个。
        # ident : 线程的唯一标识符,是一个整数值。在多线程程序中,每个线程的 ident 都是唯一的。
        # daemon : 布尔值,表示线程是否为守护线程。守护线程在主程序退出时会自动结束。
        # target : 线程启动后要执行的目标函数。
        # args : 传递给 target 函数的位置参数元组。
        # kwargs : 传递给 target 函数的关键字参数字典。
        # started : 布尔值,表示线程是否已经开始执行。
        # is_alive : 属性,与 is_alive() 方法功能相同,返回线程是否还活着。
        # 方法 :
        # start() : 启动线程。线程对象只能被启动一次。
        # run() : 一个虚拟方法,当线程启动时,会调用这个方法。默认实现会调用 target 函数,但可以被子类覆盖以自定义线程的行为。
        # is_alive() : 返回线程是否还活着(即是否已经开始且尚未结束)。
        # join([timeout]) : 等待线程终止。可选的 timeout 参数指定等待的秒数。如果 timeout 为 None ,则会无限期等待。
        # getName() : 返回线程的名称。
        # setName(name) : 设置线程的名称。
        # isDaemon() : 返回线程是否为守护线程。
        # setDaemon(daemonic) : 设置线程是否为守护线程。
        # getThreadInfo() : 返回一个包含线程信息的元组,包括线程的标识符、名称、是否为守护线程、是否已经启动等信息。

        # 在 wrapper 函数内部,创建一个新的 threading.Thread 对象。这个线程的目标函数是被装饰的函数 func ,并且将 wrapper 函数接收到的参数传递给 func 。 daemon=True 参数意味着这个线程是一个守护线程,当主程序退出时,守护线程会自动结束。
        thread = threading.Thread(target=func, args=args, kwargs=kwargs, daemon=True)
        # 启动创建的线程。
        thread.start()
        # wrapper 函数返回创建的线程对象,这样调用者可以对线程进行进一步的操作,比如等待线程结束。
        return thread

    # 装饰器 threaded 返回 wrapper 函数,这样当 @threaded 装饰器应用到一个函数上时,实际上是用 wrapper 函数包装了原始函数。
    return wrapper

5.def join_threads(verbose=False): 

# 这段代码定义了一个名为 join_threads 的函数,其目的是等待所有非主线程(即所有守护线程)完成。这个函数可以在程序退出时调用,以确保所有后台线程都已经妥善结束。
# 定义一个函数 join_threads ,它接受一个参数。
# 1.verbose :布尔参数,默认值为 False ,控制是否打印关于正在加入的线程的信息。
def join_threads(verbose=False):
    # Join all daemon threads, i.e. atexit.register(lambda: join_threads())    加入所有守护线程,即 atexit.register(lambda: join_threads())。

    # threading.current_thread()
    # threading.current_thread() 是 Python threading 模块中的一个函数,用于获取当前执行线程的引用。
    # 参数 :无参数。
    # 返回值 :
    # 返回当前执行线程的 Thread 对象。
    # 功能描述 :
    # 这个函数返回一个代表当前执行线程的 Thread 对象。这允许获取关于当前线程的信息,或者在当前线程上调用方法。
    # 使用场景 :
    # 获取当前线程的名称、标识符等属性。
    # 在当前线程上调用方法,比如 join() 或 is_alive() 。
    # 注意事项 :
    # 这个函数在任何线程中都可以调用,包括主线程。

    # 获取当前的线程对象,并将其存储在变量 main_thread 中。这是主线程的引用,稍后将用它来区分主线程和其他线程。
    main_thread = threading.current_thread()

    # threading.enumerate()
    # threading.enumerate() 是 Python threading 模块中的一个函数,它用于获取当前 Python 解释器中所有活动线程的列表。
    # 参数 :无参数。
    # 返回值 :
    # 返回一个列表,其中包含了当前活动的所有 Thread 对象。
    # 功能描述 :
    # 这个函数返回一个列表,列表中的每个元素都是一个 Thread 对象,代表当前 Python 进程中活动的所有线程。这个列表包括了主线程和所有通过 threading.Thread 创建的子线程。
    # 使用场景 :
    # 当需要获取当前所有线程的信息时。
    # 在调试或日志记录时,需要检查哪些线程正在运行。
    # 在程序退出前,需要等待所有子线程完成时。
    # 注意事项 :
    # 返回的列表不包括已经结束的线程。
    # 这个函数返回的列表是活动的线程的快照,如果程序在获取列表后创建或结束线程,这些变化不会反映在返回的列表中。

    # 使用 threading.enumerate() 函数获取当前所有活动的线程的列表,并遍历这个列表。
    for t in threading.enumerate():
        # 检查当前遍历到的线程 t 是否不是主线程。如果不是,那么它是一个需要被加入的线程。
        if t is not main_thread:
            # 如果 verbose 参数为 True ,则打印一条消息,说明正在加入线程 t 。
            if verbose:
                print(f'Joining thread {t.name}')    # 加入线程 {t.name}。
            # 调用线程 t 的 join() 方法,这将阻塞调用者,直到线程 t 完成执行。
            t.join()
# 这个函数通常用于确保在程序退出之前,所有后台线程都已经完成它们的工作。这对于避免资源泄露和确保数据一致性非常重要。

6.def notebook_init(verbose=True): 

# 这段代码定义了一个名为 notebook_init 的函数,它用于在 Jupyter Notebook 环境中初始化和检查系统软硬件配置。
# 定义一个函数 notebook_init ,它接受一个参数。
# 1.verbose :布尔参数,默认值为 True ,该参数控制是否打印详细的系统信息。
def notebook_init(verbose=True):
    # Check system software and hardware    检查系统软件和硬件。
    # 打印一条消息表示检查开始。
    print('Checking setup...')    # 检查设置...

    # 导入 os 和 shutil 模块,这些模块分别用于操作系统功能和文件操作。
    import os
    import shutil

    from utils.general import check_font, check_requirements, is_colab
    from utils.torch_utils import select_device  # imports

    # 调用 check_font 函数检查字体配置。
    # def check_font(font=FONT, progress=False): -> 检查指定的字体文件是否存在于本地,如果不存在,则从网络上下载该字体文件。
    check_font()

    # 导入 psutil 模块用于获取系统信息。
    import psutil
    # 导入 IPython.display 用于在 Jupyter Notebook 中显示图像和清除控制台输出。
    from IPython import display  # to display images and clear console output

    # 如果当前环境是 Google Colab,删除 /content/sample_data 目录以清理空间。
    if is_colab():
        shutil.rmtree('/content/sample_data', ignore_errors=True)  # remove colab /sample_data directory

    # System info
    # 如果 verbose 参数为 True ,则获取系统信息,包括 CPU 核心数、RAM 和磁盘使用情况,并格式化为字符串 s 。如果不是 verbose ,则 s 为空字符串。
    if verbose:
        gb = 1 << 30  # bytes to GiB (1024 ** 3)
        ram = psutil.virtual_memory().total
        total, used, free = shutil.disk_usage("/")
        display.clear_output()
        s = f'({os.cpu_count()} CPUs, {ram / gb:.1f} GB RAM, {(total - free) / gb:.1f}/{total / gb:.1f} GB disk)'
    else:
        s = ''

    # 调用 select_device 函数选择设备(如 GPU), newline=False 参数表示不打印新行。
    # def select_device(device='', batch_size=0, newline=True):
    # -> 根据用户提供的参数选择使用 CPU、单个 GPU 或多个 GPU,并返回一个对应的 PyTorch 设备对象。返回一个 PyTorch 设备对象,用于指定后续计算应该在哪个设备上执行。
    # -> return torch.device(arg)
    select_device(newline=False)
    # 使用 emojis 函数(未在代码中定义,可能是一个自定义函数)打印一条包含系统信息的消息,表示设置完成。
    # def emojis(str=''):
    # -> 确保在Windows系统上,任何包含emoji或其他非ASCII字符的字符串在处理时不会引发错误,方法是将这些字符忽略掉。在非Windows系统上,字符串则原样返回,因为这些系统通常对emoji有更好的支持。
    # -> return str.encode().decode('ascii', 'ignore') if platform.system() == 'Windows' else str
    print(emojis(f'Setup complete ✅ {s}'))
    # 函数返回 display 对象,这可能是为了在 Jupyter Notebook 中使用 display 的功能。
    return display
# 这个函数通常用于 Jupyter Notebook 环境中,以确保所有必要的系统配置都已满足,并且提供系统信息以便用户了解当前环境。


网站公告

今日签到

点亮在社区的每一天
去签到