NumPy 源码解析(九)

.\numpy\numpy\distutils\core.py

# 导入 sys 模块,用于系统相关操作
import sys
# 从 distutils.core 模块导入 Distribution 类,用于处理发行版相关任务
from distutils.core import Distribution

# 检查是否已导入 setuptools 模块
if 'setuptools' in sys.modules:
    have_setuptools = True
    # 如果有 setuptools,则从 setuptools 中导入 setup 函数,并重命名为 old_setup
    from setuptools import setup as old_setup
    # 导入 setuptools.command 中的 easy_install 模块,用于安装包
    # 注意:easy_install 还会导入 math 模块,可能从当前工作目录中获取
    from setuptools.command import easy_install
    try:
        # 尝试导入 setuptools.command 中的 bdist_egg 模块,用于创建 egg 包
        from setuptools.command import bdist_egg
    except ImportError:
        # 如果导入失败,表示 setuptools 版本过旧,设置 have_setuptools 为 False
        have_setuptools = False
else:
    # 如果没有导入 setuptools,则从 distutils.core 中导入 setup 函数,并重命名为 old_setup
    from distutils.core import setup as old_setup
    have_setuptools = False

# 导入 warnings 模块,用于处理警告信息
import warnings
# 导入 distutils.core 和 distutils.dist 模块,用于核心任务和发行版任务
import distutils.core
import distutils.dist

# 从 numpy.distutils.extension 模块中导入 Extension 类,用于编译扩展模块
from numpy.distutils.extension import Extension  # noqa: F401
# 从 numpy.distutils.numpy_distribution 模块中导入 NumpyDistribution 类,用于处理 NumPy 发行版
from numpy.distutils.numpy_distribution import NumpyDistribution
# 从 numpy.distutils.command 模块中导入多个命令类,用于编译、构建等任务
from numpy.distutils.command import config, config_compiler, \
     build, build_py, build_ext, build_clib, build_src, build_scripts, \
     sdist, install_data, install_headers, install, bdist_rpm, \
     install_clib
# 从 numpy.distutils.misc_util 模块中导入辅助函数 is_sequence 和 is_string
from numpy.distutils.misc_util import is_sequence, is_string

# 定义一个字典 numpy_cmdclass,存储各个命令类对应的处理类
numpy_cmdclass = {'build':            build.build,
                  'build_src':        build_src.build_src,
                  'build_scripts':    build_scripts.build_scripts,
                  'config_cc':        config_compiler.config_cc,
                  'config_fc':        config_compiler.config_fc,
                  'config':           config.config,
                  'build_ext':        build_ext.build_ext,
                  'build_py':         build_py.build_py,
                  'build_clib':       build_clib.build_clib,
                  'sdist':            sdist.sdist,
                  'install_data':     install_data.install_data,
                  'install_headers':  install_headers.install_headers,
                  'install_clib':     install_clib.install_clib,
                  'install':          install.install,
                  'bdist_rpm':        bdist_rpm.bdist_rpm,
                  }

# 如果有 setuptools 模块,则继续进行以下设置
if have_setuptools:
    # 从 numpy.distutils.command 中导入 develop 和 egg_info 模块
    from numpy.distutils.command import develop, egg_info
    # 向 numpy_cmdclass 字典中添加更多命令类和对应的处理类
    numpy_cmdclass['bdist_egg'] = bdist_egg.bdist_egg
    numpy_cmdclass['develop'] = develop.develop
    numpy_cmdclass['easy_install'] = easy_install.easy_install
    numpy_cmdclass['egg_info'] = egg_info.egg_info

def _dict_append(d, **kws):
    """向字典 d 中的键值对进行追加或更新
    
    Args:
        d (dict): 目标字典
        **kws: 关键字参数,键为要追加或更新的字典键,值为要追加或更新的对应值
    """
    for k, v in kws.items():
        if k not in d:
            d[k] = v
            continue
        dv = d[k]
        if isinstance(dv, tuple):
            d[k] = dv + tuple(v)
        elif isinstance(dv, list):
            d[k] = dv + list(v)
        elif isinstance(dv, dict):
            _dict_append(dv, **v)
        elif is_string(dv):
            d[k] = dv + v
        else:
            raise TypeError(repr(type(dv)))

def _command_line_ok(_cache=None):
    """检查命令行是否不包含任何帮助或显示请求
    
    Args:
        _cache (list, optional): 用于缓存结果的列表
    
    Returns:
        bool: 如果命令行没有包含帮助或显示请求,则返回 True,否则返回 False
    """
    if _cache:
        return _cache[0]
    elif _cache is None:
        _cache = []
    # 初始化一个布尔变量,用于标记参数是否合法,默认为True
    ok = True
    # 根据 Distribution 类的 display_option_names 属性生成展示选项列表
    display_opts = ['--'+n for n in Distribution.display_option_names]
    # 遍历 Distribution 类的 display_options 属性
    for o in Distribution.display_options:
        # 如果选项的第二个元素为真,将其简写形式添加到展示选项列表中
        if o[1]:
            display_opts.append('-'+o[1])
    # 遍历命令行参数列表
    for arg in sys.argv:
        # 如果命令行参数以 '--help' 开头,或者是 '-h',或者在展示选项列表中
        if arg.startswith('--help') or arg=='-h' or arg in display_opts:
            # 将 ok 设置为 False,表示参数不合法
            ok = False
            # 跳出循环,不再检查后续的命令行参数
            break
    # 将检查结果添加到 _cache 列表中
    _cache.append(ok)
    # 返回参数合法性的检查结果
    return ok
def get_distribution(always=False):
    # 获取当前的分发对象
    dist = distutils.core._setup_distribution
    # XXX Hack to get numpy installable with easy_install.
    # The problem is easy_install runs it's own setup(), which
    # sets up distutils.core._setup_distribution. However,
    # when our setup() runs, that gets overwritten and lost.
    # We can't use isinstance, as the DistributionWithoutHelpCommands
    # class is local to a function in setuptools.command.easy_install
    # 这段代码用来处理使用 easy_install 安装 numpy 的问题。
    # easy_install 会运行自己的 setup(),设置了 distutils.core._setup_distribution。
    # 当我们的 setup() 运行时,会覆盖并丢失这个设置。通过这段代码来修复这个问题。
    if dist is not None and \
            'DistributionWithoutHelpCommands' in repr(dist):
        dist = None
    if always and dist is None:
        # 如果指定了 always=True 并且 dist 为 None,则使用 NumpyDistribution 类
        dist = NumpyDistribution()
    return dist

def setup(**attr):

    cmdclass = numpy_cmdclass.copy()

    new_attr = attr.copy()
    if 'cmdclass' in new_attr:
        # 更新 cmdclass,如果在 attr 中指定了 cmdclass
        cmdclass.update(new_attr['cmdclass'])
    new_attr['cmdclass'] = cmdclass

    if 'configuration' in new_attr:
        # To avoid calling configuration if there are any errors
        # or help request in command in the line.
        # 如果命令行中存在错误或者帮助请求,避免调用 configuration 方法。
        configuration = new_attr.pop('configuration')

        old_dist = distutils.core._setup_distribution
        old_stop = distutils.core._setup_stop_after
        distutils.core._setup_distribution = None
        distutils.core._setup_stop_after = "commandline"
        try:
            # 递归调用 setup(),处理新的属性
            dist = setup(**new_attr)
        finally:
            # 恢复原来的 _setup_distribution 和 _setup_stop_after 设置
            distutils.core._setup_distribution = old_dist
            distutils.core._setup_stop_after = old_stop
        if dist.help or not _command_line_ok():
            # 如果显示了帮助信息或者命令行状态不正确,直接返回 dist
            # 跳过运行任何命令
            return dist

        # create setup dictionary and append to new_attr
        # 创建配置字典并添加到 new_attr
        config = configuration()
        if hasattr(config, 'todict'):
            config = config.todict()
        _dict_append(new_attr, **config)

    # Move extension source libraries to libraries
    # 将扩展模块的源代码库移动到 libraries 中
    libraries = []
    for ext in new_attr.get('ext_modules', []):
        new_libraries = []
        for item in ext.libraries:
            if is_sequence(item):
                lib_name, build_info = item
                _check_append_ext_library(libraries, lib_name, build_info)
                new_libraries.append(lib_name)
            elif is_string(item):
                new_libraries.append(item)
            else:
                raise TypeError("invalid description of extension module "
                                "library %r" % (item,))
        ext.libraries = new_libraries
    if libraries:
        if 'libraries' not in new_attr:
            new_attr['libraries'] = []
        for item in libraries:
            _check_append_library(new_attr['libraries'], item)

    # sources in ext_modules or libraries may contain header files
    # ext_modules 或 libraries 中可能包含头文件
    if ('ext_modules' in new_attr or 'libraries' in new_attr) \
       and 'headers' not in new_attr:
        new_attr['headers'] = []

    # Use our custom NumpyDistribution class instead of distutils' one
    # 使用我们自定义的 NumpyDistribution 类,替代 distutils 的类
    new_attr['distclass'] = NumpyDistribution

    return old_setup(**new_attr)
# 检查并向库列表中追加新的库项或更新现有库项的构建信息(如果存在)
def _check_append_library(libraries, item):
    # 遍历库列表中的每一项
    for libitem in libraries:
        # 检查当前库项是否为序列(元组或列表)
        if is_sequence(libitem):
            # 如果待添加的项也是序列
            if is_sequence(item):
                # 如果两个序列的第一个元素相等
                if item[0] == libitem[0]:
                    # 如果第二个元素也相等,则表示已存在相同的库项
                    if item[1] is libitem[1]:
                        return  # 直接返回,无需更新
                    # 如果第二个元素不相等,则发出警告
                    warnings.warn("[0] libraries list contains %r with"
                                  " different build_info" % (item[0],),
                                  stacklevel=2)
                    break
            else:
                # 如果待添加的项不是序列,但与库项的第一个元素相等
                if item == libitem[0]:
                    # 发出相应的警告
                    warnings.warn("[1] libraries list contains %r with"
                                  " no build_info" % (item[0],),
                                  stacklevel=2)
                    break
        else:
            # 如果库项本身不是序列,检查待添加的项是否为序列
            if is_sequence(item):
                # 如果待添加的项的第一个元素与当前库项相等
                if item[0] == libitem:
                    # 发出相应的警告
                    warnings.warn("[2] libraries list contains %r with"
                                  " no build_info" % (item[0],),
                                  stacklevel=2)
                    break
            else:
                # 如果两者相等,则表示已存在相同的库项
                if item == libitem:
                    return  # 直接返回,无需更新

    # 如果未发现相同的库项,则将新的库项添加到列表末尾
    libraries.append(item)

# 检查并向外部库列表中追加新的库项或更新现有库项的构建信息(如果存在)
def _check_append_ext_library(libraries, lib_name, build_info):
    # 遍历库列表中的每一项
    for item in libraries:
        # 检查当前库项是否为序列(元组或列表)
        if is_sequence(item):
            # 如果库项是一个序列,并且序列的第一个元素与指定的库名相等
            if item[0] == lib_name:
                # 如果序列的第二个元素也相等,则表示已存在相同的库项
                if item[1] is build_info:
                    return  # 直接返回,无需更新
                # 如果第二个元素不相等,则发出警告
                warnings.warn("[3] libraries list contains %r with"
                              " different build_info" % (lib_name,),
                              stacklevel=2)
                break
        else:
            # 如果当前库项不是序列,并且与指定的库名相等
            if item == lib_name:
                # 发出相应的警告
                warnings.warn("[4] libraries list contains %r with"
                              " no build_info" % (lib_name,),
                              stacklevel=2)
                break

    # 如果未发现相同的库项,则将新的库名和构建信息添加为元组到列表末尾
    libraries.append((lib_name, build_info))

.\numpy\numpy\distutils\cpuinfo.py

#!/usr/bin/env python3
"""
cpuinfo

Copyright 2002 Pearu Peterson all rights reserved,
Pearu Peterson <pearu@cens.ioc.ee>
Permission to use, modify, and distribute this software is given under the
terms of the NumPy (BSD style) license.  See LICENSE.txt that came with
this distribution for specifics.

NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
Pearu Peterson

"""

# 导入必要的模块和库
import os                    # 操作系统接口
import platform              # 获取平台信息
import re                    # 正则表达式库
import sys                   # 提供对解释器相关功能的访问
import types                 # Python类型相关的操作
import warnings              # 警告控制

from subprocess import getstatusoutput   # 获取命令行输出状态和内容


def getoutput(cmd, successful_status=(0,), stacklevel=1):
    # 尝试执行命令并获取输出和状态
    try:
        status, output = getstatusoutput(cmd)
    except OSError as e:
        # 捕获操作系统异常并发出警告
        warnings.warn(str(e), UserWarning, stacklevel=stacklevel)
        return False, ""
    # 检查状态是否在成功状态列表中,并返回结果和输出内容
    if os.WIFEXITED(status) and os.WEXITSTATUS(status) in successful_status:
        return True, output
    return False, output

def command_info(successful_status=(0,), stacklevel=1, **kw):
    # 执行一组命令并收集输出信息
    info = {}
    for key in kw:
        ok, output = getoutput(kw[key], successful_status=successful_status,
                               stacklevel=stacklevel+1)
        if ok:
            info[key] = output.strip()
    return info

def command_by_line(cmd, successful_status=(0,), stacklevel=1):
    # 执行命令并逐行获取输出内容
    ok, output = getoutput(cmd, successful_status=successful_status,
                           stacklevel=stacklevel+1)
    if not ok:
        return
    for line in output.splitlines():
        yield line.strip()

def key_value_from_command(cmd, sep, successful_status=(0,),
                           stacklevel=1):
    # 从命令输出中获取键值对信息
    d = {}
    for line in command_by_line(cmd, successful_status=successful_status,
                                stacklevel=stacklevel+1):
        l = [s.strip() for s in line.split(sep, 1)]
        if len(l) == 2:
            d[l[0]] = l[1]
    return d

class CPUInfoBase:
    """Holds CPU information and provides methods for requiring
    the availability of various CPU features.
    """

    def _try_call(self, func):
        # 尝试调用给定函数,捕获任何异常
        try:
            return func()
        except Exception:
            pass

    def __getattr__(self, name):
        # 获取未定义的属性时的默认处理方法
        if not name.startswith('_'):
            if hasattr(self, '_'+name):
                attr = getattr(self, '_'+name)
                if isinstance(attr, types.MethodType):
                    return lambda func=self._try_call,attr=attr : func(attr)
            else:
                return lambda : None
        raise AttributeError(name)

    def _getNCPUs(self):
        # 返回 CPU 数量(这里默认为1)
        return 1

    def __get_nbits(self):
        # 获取系统位数(32位或64位)
        abits = platform.architecture()[0]
        nbits = re.compile(r'(\d+)bit').search(abits).group(1)
        return nbits

    def _is_32bit(self):
        # 检查系统是否为32位
        return self.__get_nbits() == '32'

    def _is_64bit(self):
        # 检查系统是否为64位
        return self.__get_nbits() == '64'

class LinuxCPUInfo(CPUInfoBase):
    # Linux 特定的 CPU 信息类
    info = None
    # 初始化方法,用于初始化实例的信息
    def __init__(self):
        # 如果实例的信息已经存在,则直接返回,不执行后续代码
        if self.info is not None:
            return
        # 初始化一个空的信息列表
        info = [ {} ]
        # 获取系统命令 'uname -m' 的输出
        ok, output = getoutput('uname -m')
        # 如果获取成功
        if ok:
            # 将获取的输出去除首尾空白字符,存入info[0]的键 'uname_m' 中
            info[0]['uname_m'] = output.strip()
        try:
            # 尝试打开 '/proc/cpuinfo' 文件
            fo = open('/proc/cpuinfo')
        except OSError as e:
            # 如果打开文件失败,发出警告并抛出异常信息
            warnings.warn(str(e), UserWarning, stacklevel=2)
        else:
            # 如果打开文件成功,遍历文件的每一行
            for line in fo:
                # 分割每行内容,得到键值对列表,去除首尾空白字符
                name_value = [s.strip() for s in line.split(':', 1)]
                # 如果分割后的列表不是长度为2,跳过当前循环
                if len(name_value) != 2:
                    continue
                # 分别取出键和值
                name, value = name_value
                # 如果info为空或者name已经在info[-1]中存在,说明是下一个处理器信息
                if not info or name in info[-1]: # next processor
                    info.append({})
                # 将当前处理器的键值对存入info[-1]中
                info[-1][name] = value
            # 关闭文件流
            fo.close()
        # 将处理后的信息列表赋值给当前实例的类属性info
        self.__class__.info = info

    # 未实现的方法,占位用
    def _not_impl(self): pass

    # 判断当前处理器是否为AMD系列
    def _is_AMD(self):
        return self.info[0]['vendor_id']=='AuthenticAMD'

    # 判断当前处理器是否为AMD Athlon K6-2
    def _is_AthlonK6_2(self):
        return self._is_AMD() and self.info[0]['model'] == '2'

    # 判断当前处理器是否为AMD Athlon K6-3
    def _is_AthlonK6_3(self):
        return self._is_AMD() and self.info[0]['model'] == '3'

    # 判断当前处理器是否为AMD K6系列
    def _is_AthlonK6(self):
        return re.match(r'.*?AMD-K6', self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD K7系列
    def _is_AthlonK7(self):
        return re.match(r'.*?AMD-K7', self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Athlon MP
    def _is_AthlonMP(self):
        return re.match(r'.*?Athlon\(tm\) MP\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD 64位处理器
    def _is_AMD64(self):
        return self.is_AMD() and self.info[0]['family'] == '15'

    # 判断当前处理器是否为AMD Athlon 64
    def _is_Athlon64(self):
        return re.match(r'.*?Athlon\(tm\) 64\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Athlon HX
    def _is_AthlonHX(self):
        return re.match(r'.*?Athlon HX\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Opteron
    def _is_Opteron(self):
        return re.match(r'.*?Opteron\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为AMD Hammer
    def _is_Hammer(self):
        return re.match(r'.*?Hammer\b',
                        self.info[0]['model name']) is not None

    # 判断当前处理器是否为Alpha系列
    def _is_Alpha(self):
        return self.info[0]['cpu']=='Alpha'

    # 判断当前处理器是否为Alpha EV4
    def _is_EV4(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV4'

    # 判断当前处理器是否为Alpha EV5
    def _is_EV5(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV5'

    # 判断当前处理器是否为Alpha EV56
    def _is_EV56(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'EV56'

    # 判断当前处理器是否为Alpha PCA56
    def _is_PCA56(self):
        return self.is_Alpha() and self.info[0]['cpu model'] == 'PCA56'

    # 判断当前处理器是否为Intel系列
    def _is_Intel(self):
        return self.info[0]['vendor_id']=='GenuineIntel'

    # 判断当前处理器是否为Intel i486
    def _is_i486(self):
        return self.info[0]['cpu']=='i486'

    # 判断当前处理器是否为Intel i586
    def _is_i586(self):
        return self.is_Intel() and self.info[0]['cpu family'] == '5'

    # 判断当前处理器是否为Intel i686
    def _is_i686(self):
        return self.is_Intel() and self.info[0]['cpu family'] == '6'
    # 判断CPU型号是否包含'Celeron'
    def _is_Celeron(self):
        return re.match(r'.*?Celeron',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'
    def _is_Pentium(self):
        return re.match(r'.*?Pentium',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'II'
    def _is_PentiumII(self):
        return re.match(r'.*?Pentium.*?II\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否为'PentiumPro'
    def _is_PentiumPro(self):
        return re.match(r'.*?PentiumPro\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'MMX'
    def _is_PentiumMMX(self):
        return re.match(r'.*?Pentium.*?MMX\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'III'
    def _is_PentiumIII(self):
        return re.match(r'.*?Pentium.*?III\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'IV'或者'4'
    def _is_PentiumIV(self):
        return re.match(r'.*?Pentium.*?(IV|4)\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否包含'Pentium'和'M'
    def _is_PentiumM(self):
        return re.match(r'.*?Pentium.*?M\b',
                        self.info[0]['model name']) is not None
    
    # 判断CPU型号是否为'Prescott',即为Pentium IV且具有SSE3指令集
    def _is_Prescott(self):
        return (self.is_PentiumIV() and self.has_sse3())
    
    # 判断CPU型号是否为'Nocona',即为Intel系列、特定CPU family、具有SSE3但不具有SSSE3并包含'lm'标志
    def _is_Nocona(self):
        return (self.is_Intel()
                and (self.info[0]['cpu family'] == '6'
                     or self.info[0]['cpu family'] == '15')
                and (self.has_sse3() and not self.has_ssse3())
                and re.match(r'.*?\blm\b', self.info[0]['flags']) is not None)
    
    # 判断CPU型号是否为'Core2',即为64位、Intel系列且包含'Core(TM)2'标志
    def _is_Core2(self):
        return (self.is_64bit() and self.is_Intel() and
                re.match(r'.*?Core\(TM\)2\b',
                         self.info[0]['model name']) is not None)
    
    # 判断CPU型号是否包含'Itanium'
    def _is_Itanium(self):
        return re.match(r'.*?Itanium\b',
                        self.info[0]['family']) is not None
    
    # 判断CPU型号是否包含'XEON'(不区分大小写)
    def _is_XEON(self):
        return re.match(r'.*?XEON\b',
                        self.info[0]['model name'], re.IGNORECASE) is not None
    
    # _is_Xeon 是 _is_XEON 的别名
    
    # 判断是否只有一个CPU
    def _is_singleCPU(self):
        return len(self.info) == 1
    
    # 获取CPU数量
    def _getNCPUs(self):
        return len(self.info)
    
    # 判断CPU是否具有fdiv错误
    def _has_fdiv_bug(self):
        return self.info[0]['fdiv_bug']=='yes'
    
    # 判断CPU是否具有f00f错误
    def _has_f00f_bug(self):
        return self.info[0]['f00f_bug']=='yes'
    
    # 判断CPU是否支持MMX指令集
    def _has_mmx(self):
        return re.match(r'.*?\bmmx\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSE指令集
    def _has_sse(self):
        return re.match(r'.*?\bsse\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSE2指令集
    def _has_sse2(self):
        return re.match(r'.*?\bsse2\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSE3指令集
    def _has_sse3(self):
        return re.match(r'.*?\bpni\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持SSSE3指令集
    def _has_ssse3(self):
        return re.match(r'.*?\bssse3\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持3DNow指令集
    def _has_3dnow(self):
        return re.match(r'.*?\b3dnow\b', self.info[0]['flags']) is not None
    
    # 判断CPU是否支持3DNowExt指令集
    def _has_3dnowext(self):
        return re.match(r'.*?\b3dnowext\b', self.info[0]['flags']) is not None
class IRIXCPUInfo(CPUInfoBase):
    # IRIXCPUInfo 类,继承自 CPUInfoBase

    info = None
    # 类变量 info,用于存储系统信息,初始值为 None

    def __init__(self):
        # 初始化方法
        if self.info is not None:
            return
        # 如果 info 已经被设置过,则直接返回,避免重复初始化

        # 调用 key_value_from_command 函数获取系统信息,命令为 'sysconf',分隔符为 ' '
        # 只接受状态码为 0 或 1 的执行结果
        info = key_value_from_command('sysconf', sep=' ',
                                      successful_status=(0, 1))
        # 设置类变量 info 为获取到的系统信息
        self.__class__.info = info

    def _not_impl(self): pass
    # 占位方法,未实现的方法,不做任何操作

    def _is_singleCPU(self):
        # 判断是否为单 CPU 系统,根据 info 中的 'NUM_PROCESSORS' 值来判断
        return self.info.get('NUM_PROCESSORS') == '1'

    def _getNCPUs(self):
        # 获取 CPU 数量,如果 'NUM_PROCESSORS' 存在则返回其整数值,否则返回默认值 1
        return int(self.info.get('NUM_PROCESSORS', 1))

    def __cputype(self, n):
        # 辅助方法,用于判断 CPU 类型是否为指定编号 n
        return self.info.get('PROCESSORS').split()[0].lower() == 'r%s' % (n)

    def _is_r2000(self): return self.__cputype(2000)
    def _is_r3000(self): return self.__cputype(3000)
    def _is_r3900(self): return self.__cputype(3900)
    def _is_r4000(self): return self.__cputype(4000)
    def _is_r4100(self): return self.__cputype(4100)
    def _is_r4300(self): return self.__cputype(4300)
    def _is_r4400(self): return self.__cputype(4400)
    def _is_r4600(self): return self.__cputype(4600)
    def _is_r4650(self): return self.__cputype(4650)
    def _is_r5000(self): return self.__cputype(5000)
    def _is_r6000(self): return self.__cputype(6000)
    def _is_r8000(self): return self.__cputype(8000)
    def _is_r10000(self): return self.__cputype(10000)
    def _is_r12000(self): return self.__cputype(12000)
    def _is_rorion(self): return self.__cputype('orion')

    def get_ip(self):
        # 获取主机名(IP),如果出错则忽略异常
        try: return self.info.get('MACHINE')
        except Exception: pass

    def __machine(self, n):
        # 辅助方法,用于判断主机类型是否为指定编号 n
        return self.info.get('MACHINE').lower() == 'ip%s' % (n)

    def _is_IP19(self): return self.__machine(19)
    def _is_IP20(self): return self.__machine(20)
    def _is_IP21(self): return self.__machine(21)
    def _is_IP22(self): return self.__machine(22)
    def _is_IP22_4k(self): return self.__machine(22) and self._is_r4000()
    def _is_IP22_5k(self): return self.__machine(22) and self._is_r5000()
    def _is_IP24(self): return self.__machine(24)
    def _is_IP25(self): return self.__machine(25)
    def _is_IP26(self): return self.__machine(26)
    def _is_IP27(self): return self.__machine(27)
    def _is_IP28(self): return self.__machine(28)
    def _is_IP30(self): return self.__machine(30)
    def _is_IP32(self): return self.__machine(32)
    def _is_IP32_5k(self): return self.__machine(32) and self._is_r5000()
    def _is_IP32_10k(self): return self.__machine(32) and self._is_r10000()


class DarwinCPUInfo(CPUInfoBase):
    # DarwinCPUInfo 类,继承自 CPUInfoBase

    info = None
    # 类变量 info,用于存储系统信息,初始值为 None

    def __init__(self):
        # 初始化方法
        if self.info is not None:
            return
        # 如果 info 已经被设置过,则直接返回,避免重复初始化

        # 调用 command_info 函数获取系统信息,包括 'arch' 和 'machine' 的命令结果
        info = command_info(arch='arch',
                            machine='machine')
        # 使用 sysctl 命令获取更多硬件相关信息,将其存储在 'sysctl_hw' 键下
        info['sysctl_hw'] = key_value_from_command('sysctl hw', sep='=')
        # 设置类变量 info 为获取到的所有系统信息
        self.__class__.info = info

    def _not_impl(self): pass
    # 占位方法,未实现的方法,不做任何操作

    def _getNCPUs(self):
        # 获取 CPU 数量,从 sysctl_hw 字典中获取 'hw.ncpu' 键值,如果不存在则返回默认值 1
        return int(self.info['sysctl_hw'].get('hw.ncpu', 1))

    def _is_Power_Macintosh(self):
        # 判断当前系统是否为 Power Macintosh
        return self.info['sysctl_hw']['hw.machine']=='Power Macintosh'
    # 判断当前系统架构是否为 i386
    def _is_i386(self):
        return self.info['arch']=='i386'
    
    # 判断当前系统架构是否为 ppc
    def _is_ppc(self):
        return self.info['arch']=='ppc'
    
    # 检查当前系统的具体机器型号是否为给定的 PPC 架构类型
    def __machine(self, n):
        return self.info['machine'] == 'ppc%s'%n
    
    # 下面一系列方法用于检查当前系统是否为特定的 PPC 机器型号
    def _is_ppc601(self): return self.__machine(601)
    def _is_ppc602(self): return self.__machine(602)
    def _is_ppc603(self): return self.__machine(603)
    def _is_ppc603e(self): return self.__machine('603e')
    def _is_ppc604(self): return self.__machine(604)
    def _is_ppc604e(self): return self.__machine('604e')
    def _is_ppc620(self): return self.__machine(620)
    def _is_ppc630(self): return self.__machine(630)
    def _is_ppc740(self): return self.__machine(740)
    def _is_ppc7400(self): return self.__machine(7400)
    def _is_ppc7450(self): return self.__machine(7450)
    def _is_ppc750(self): return self.__machine(750)
    def _is_ppc403(self): return self.__machine(403)
    def _is_ppc505(self): return self.__machine(505)
    def _is_ppc801(self): return self.__machine(801)
    def _is_ppc821(self): return self.__machine(821)
    def _is_ppc823(self): return self.__machine(823)
    def _is_ppc860(self): return self.__machine(860)
# 定义一个名为 SunOSCPUInfo 的类,继承自 CPUInfoBase 类
class SunOSCPUInfo(CPUInfoBase):

    # 类变量 info,用于存储系统信息,初始化为 None
    info = None

    # 构造函数,初始化对象实例
    def __init__(self):
        # 如果类变量 info 不为 None,则直接返回,避免重复初始化
        if self.info is not None:
            return
        
        # 调用 command_info 函数获取系统信息,包括架构、机器类型、内核信息等
        info = command_info(arch='arch',
                            mach='mach',
                            uname_i='uname_i',
                            isainfo_b='isainfo -b',
                            isainfo_n='isainfo -n',
                            )
        
        # 调用 key_value_from_command 函数获取并添加额外的 uname -X 命令返回的键值对信息到 info 字典中
        info['uname_X'] = key_value_from_command('uname -X', sep='=')
        
        # 通过迭代 psrinfo -v 0 命令返回的每一行,使用正则表达式匹配处理器信息,并将结果添加到 info 字典中
        for line in command_by_line('psrinfo -v 0'):
            m = re.match(r'\s*The (?P<p>[\w\d]+) processor operates at', line)
            if m:
                info['processor'] = m.group('p')
                break
        
        # 将当前实例的类变量 info 设置为获取到的系统信息
        self.__class__.info = info

    # 以下是一系列用于检测特定硬件或软件特征的方法,每个方法都返回布尔值

    # 检测系统是否为 i386 架构
    def _is_i386(self):
        return self.info['isainfo_n']=='i386'

    # 检测系统是否为 sparc 架构
    def _is_sparc(self):
        return self.info['isainfo_n']=='sparc'

    # 检测系统是否为 sparcv9 架构
    def _is_sparcv9(self):
        return self.info['isainfo_n']=='sparcv9'

    # 获取系统中 CPU 的数量,如果未指定则默认为 1
    def _getNCPUs(self):
        return int(self.info['uname_X'].get('NumCPU', 1))

    # 检测系统是否为 sun4 架构
    def _is_sun4(self):
        return self.info['arch']=='sun4'

    # 检测 uname_i 是否以 SUNW 开头,表示系统是否为 SUNW 类型
    def _is_SUNW(self):
        return re.match(r'SUNW', self.info['uname_i']) is not None

    # 检测 uname_i 是否包含字符串 SPARCstation-5,表示系统是否为 SPARCstation-5 型号
    def _is_sparcstation5(self):
        return re.match(r'.*SPARCstation-5', self.info['uname_i']) is not None

    # 检测 uname_i 是否包含字符串 Ultra-1,表示系统是否为 Ultra-1 型号
    def _is_ultra1(self):
        return re.match(r'.*Ultra-1', self.info['uname_i']) is not None

    # 检测 uname_i 是否包含字符串 Ultra-250,表示系统是否为 Ultra-250 型号
    def _is_ultra250(self):
        return re.match(r'.*Ultra-250', self.info['uname_i']) is not None

    # 以下方法类似,用于检测其他型号
    def _is_ultra2(self):
        return re.match(r'.*Ultra-2', self.info['uname_i']) is not None

    def _is_ultra30(self):
        return re.match(r'.*Ultra-30', self.info['uname_i']) is not None

    def _is_ultra4(self):
        return re.match(r'.*Ultra-4', self.info['uname_i']) is not None

    def _is_ultra5_10(self):
        return re.match(r'.*Ultra-5_10', self.info['uname_i']) is not None

    def _is_ultra5(self):
        return re.match(r'.*Ultra-5', self.info['uname_i']) is not None

    def _is_ultra60(self):
        return re.match(r'.*Ultra-60', self.info['uname_i']) is not None

    def _is_ultra80(self):
        return re.match(r'.*Ultra-80', self.info['uname_i']) is not None

    def _is_ultraenterprice(self):
        return re.match(r'.*Ultra-Enterprise', self.info['uname_i']) is not None

    def _is_ultraenterprice10k(self):
        return re.match(r'.*Ultra-Enterprise-10000', self.info['uname_i']) is not None

    def _is_sunfire(self):
        return re.match(r'.*Sun-Fire', self.info['uname_i']) is not None

    def _is_ultra(self):
        return re.match(r'.*Ultra', self.info['uname_i']) is not None

    # 检测当前处理器是否为 sparcv7 架构
    def _is_cpusparcv7(self):
        return self.info['processor']=='sparcv7'

    # 检测当前处理器是否为 sparcv8 架构
    def _is_cpusparcv8(self):
        return self.info['processor']=='sparcv8'

    # 检测当前处理器是否为 sparcv9 架构
    def _is_cpusparcv9(self):
        return self.info['processor']=='sparcv9'


# 定义一个名为 Win32CPUInfo 的类,继承自 CPUInfoBase 类
class Win32CPUInfo(CPUInfoBase):

    # 类变量 info,用于存储系统信息,初始化为 None
    info = None
    pkey = r"HARDWARE\DESCRIPTION\System\CentralProcessor"
    # 定义注册表路径,指定到处理器信息的位置

    # 构造函数初始化
    def __init__(self):
        if self.info is not None:
            return
        info = []
        try:
            # 尝试导入winreg模块,用于访问Windows注册表
            import winreg

            # 正则表达式匹配处理器标识信息的模式
            prgx = re.compile(r"family\s+(?P<FML>\d+)\s+model\s+(?P<MDL>\d+)"
                              r"\s+stepping\s+(?P<STP>\d+)", re.IGNORECASE)
            # 打开注册表指定路径下的键
            chnd=winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, self.pkey)
            pnum=0
            # 遍历处理器子键
            while True:
                try:
                    proc=winreg.EnumKey(chnd, pnum)
                except winreg.error:
                    break
                else:
                    pnum+=1
                    # 向信息列表添加处理器名称
                    info.append({"Processor":proc})
                    # 打开处理器子键
                    phnd=winreg.OpenKey(chnd, proc)
                    pidx=0
                    # 遍历处理器子键中的值
                    while True:
                        try:
                            name, value, vtpe=winreg.EnumValue(phnd, pidx)
                        except winreg.error:
                            break
                        else:
                            pidx=pidx+1
                            # 将处理器属性及其值添加到信息列表最后一个字典中
                            info[-1][name]=value
                            # 如果属性名为"Identifier",则使用正则表达式解析处理器标识信息
                            if name=="Identifier":
                                srch=prgx.search(value)
                                if srch:
                                    info[-1]["Family"]=int(srch.group("FML"))
                                    info[-1]["Model"]=int(srch.group("MDL"))
                                    info[-1]["Stepping"]=int(srch.group("STP"))
        except Exception as e:
            # 捕获异常并打印错误信息,忽略处理器信息的获取错误
            print(e, '(ignoring)')
        # 将获取的处理器信息赋给类属性info
        self.__class__.info = info

    # 未实现的方法,占位符方法
    def _not_impl(self): pass

    # Athlon处理器判断方法
    def _is_AMD(self):
        return self.info[0]['VendorIdentifier']=='AuthenticAMD'

    # Am486处理器判断方法
    def _is_Am486(self):
        return self.is_AMD() and self.info[0]['Family']==4

    # Am5x86处理器判断方法
    def _is_Am5x86(self):
        return self.is_AMD() and self.info[0]['Family']==4

    # AMDK5处理器判断方法
    def _is_AMDK5(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model'] in [0, 1, 2, 3]

    # AMDK6处理器判断方法
    def _is_AMDK6(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model'] in [6, 7]

    # AMDK6_2处理器判断方法
    def _is_AMDK6_2(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model']==8

    # AMDK6_3处理器判断方法
    def _is_AMDK6_3(self):
        return self.is_AMD() and self.info[0]['Family']==5 \
               and self.info[0]['Model']==9

    # AMDK7处理器判断方法
    def _is_AMDK7(self):
        return self.is_AMD() and self.info[0]['Family'] == 6

    # 要可靠地区分不同类型的AMD64芯片(如Athlon64、Operton、Athlon64 X2、Semperon、Turion 64等)
    # 需要查看cpuid的“brand”信息
    # 判断当前 CPU 是否为 AMD64 架构
    def _is_AMD64(self):
        return self.is_AMD() and self.info[0]['Family'] == 15

    # 判断当前 CPU 是否为 Intel 厂商
    def _is_Intel(self):
        return self.info[0]['VendorIdentifier']=='GenuineIntel'

    # 判断当前 CPU 是否为 Intel 386 系列
    def _is_i386(self):
        return self.info[0]['Family']==3

    # 判断当前 CPU 是否为 Intel 486 系列
    def _is_i486(self):
        return self.info[0]['Family']==4

    # 判断当前 CPU 是否为 Intel 586 系列
    def _is_i586(self):
        return self.is_Intel() and self.info[0]['Family']==5

    # 判断当前 CPU 是否为 Intel 686 系列
    def _is_i686(self):
        return self.is_Intel() and self.info[0]['Family']==6

    # 判断当前 CPU 是否为 Pentium 系列
    def _is_Pentium(self):
        return self.is_Intel() and self.info[0]['Family']==5

    # 判断当前 CPU 是否为 Pentium MMX
    def _is_PentiumMMX(self):
        return self.is_Intel() and self.info[0]['Family']==5 \
               and self.info[0]['Model']==4

    # 判断当前 CPU 是否为 Pentium Pro
    def _is_PentiumPro(self):
        return self.is_Intel() and self.info[0]['Family']==6 \
               and self.info[0]['Model']==1

    # 判断当前 CPU 是否为 Pentium II
    def _is_PentiumII(self):
        return self.is_Intel() and self.info[0]['Family']==6 \
               and self.info[0]['Model'] in [3, 5, 6]

    # 判断当前 CPU 是否为 Pentium III
    def _is_PentiumIII(self):
        return self.is_Intel() and self.info[0]['Family']==6 \
               and self.info[0]['Model'] in [7, 8, 9, 10, 11]

    # 判断当前 CPU 是否为 Pentium IV
    def _is_PentiumIV(self):
        return self.is_Intel() and self.info[0]['Family']==15

    # 判断当前 CPU 是否为 Pentium M
    def _is_PentiumM(self):
        return self.is_Intel() and self.info[0]['Family'] == 6 \
               and self.info[0]['Model'] in [9, 13, 14]

    # 判断当前 CPU 是否为 Core 2
    def _is_Core2(self):
        return self.is_Intel() and self.info[0]['Family'] == 6 \
               and self.info[0]['Model'] in [15, 16, 17]

    # 判断系统是否只有单个 CPU
    def _is_singleCPU(self):
        return len(self.info) == 1

    # 获取系统中 CPU 的数量
    def _getNCPUs(self):
        return len(self.info)

    # 判断当前 CPU 是否支持 MMX 指令集
    def _has_mmx(self):
        if self.is_Intel():
            return (self.info[0]['Family']==5 and self.info[0]['Model']==4) \
                   or (self.info[0]['Family'] in [6, 15])
        elif self.is_AMD():
            return self.info[0]['Family'] in [5, 6, 15]
        else:
            return False

    # 判断当前 CPU 是否支持 SSE 指令集
    def _has_sse(self):
        if self.is_Intel():
            return ((self.info[0]['Family']==6 and
                     self.info[0]['Model'] in [7, 8, 9, 10, 11])
                     or self.info[0]['Family']==15)
        elif self.is_AMD():
            return ((self.info[0]['Family']==6 and
                     self.info[0]['Model'] in [6, 7, 8, 10])
                     or self.info[0]['Family']==15)
        else:
            return False

    # 判断当前 CPU 是否支持 SSE2 指令集
    def _has_sse2(self):
        if self.is_Intel():
            return self.is_Pentium4() or self.is_PentiumM() \
                   or self.is_Core2()
        elif self.is_AMD():
            return self.is_AMD64()
        else:
            return False

    # 判断当前 CPU 是否支持 3DNow 指令集
    def _has_3dnow(self):
        return self.is_AMD() and self.info[0]['Family'] in [5, 6, 15]

    # 判断当前 CPU 是否支持 3DNowExt 指令集
    def _has_3dnowext(self):
        return self.is_AMD() and self.info[0]['Family'] in [6, 15]
# 检查操作系统平台,确定使用哪个 CPU 信息类
if sys.platform.startswith('linux'): # variations: linux2,linux-i386 (any others?)
    # 如果是 Linux 系统,选择 LinuxCPUInfo 类
    cpuinfo = LinuxCPUInfo
elif sys.platform.startswith('irix'):
    # 如果是 IRIX 系统,选择 IRIXCPUInfo 类
    cpuinfo = IRIXCPUInfo
elif sys.platform == 'darwin':
    # 如果是 Darwin(Mac OS X)系统,选择 DarwinCPUInfo 类
    cpuinfo = DarwinCPUInfo
elif sys.platform.startswith('sunos'):
    # 如果是 SunOS 系统,选择 SunOSCPUInfo 类
    cpuinfo = SunOSCPUInfo
elif sys.platform.startswith('win32'):
    # 如果是 Windows 系统,选择 Win32CPUInfo 类
    cpuinfo = Win32CPUInfo
elif sys.platform.startswith('cygwin'):
    # 如果是 Cygwin 系统,选择 LinuxCPUInfo 类(Cygwin 可以通过 LinuxCPUInfo 访问)
    cpuinfo = LinuxCPUInfo
#XXX: other OS's. Eg. use _winreg on Win32. Or os.uname on unices.
else:
    # 如果是其它操作系统,选择 CPUInfoBase 类作为默认
    cpuinfo = CPUInfoBase

# 创建 CPU 信息类的实例
cpu = cpuinfo()

# 下面的代码块不需要注释,因为它们已经被注释掉了,不会执行

.\numpy\numpy\distutils\exec_command.py

"""
exec_command

Implements exec_command function that is (almost) equivalent to
commands.getstatusoutput function but on NT, DOS systems the
returned status is actually correct (though, the returned status
values may be different by a factor). In addition, exec_command
takes keyword arguments for (re-)defining environment variables.

Provides functions:

  exec_command  --- execute command in a specified directory and
                    in the modified environment.
  find_executable --- locate a command using info from environment
                    variable PATH. Equivalent to posix `which`
                    command.

Author: Pearu Peterson <pearu@cens.ioc.ee>
Created: 11 January 2003

Requires: Python 2.x

Successfully tested on:

========  ============  =================================================
os.name   sys.platform  comments
========  ============  =================================================
posix     linux2        Debian (sid) Linux, Python 2.1.3+, 2.2.3+, 2.3.3
                        PyCrust 0.9.3, Idle 1.0.2
posix     linux2        Red Hat 9 Linux, Python 2.1.3, 2.2.2, 2.3.2
posix     sunos5        SunOS 5.9, Python 2.2, 2.3.2
posix     darwin        Darwin 7.2.0, Python 2.3
nt        win32         Windows Me
                        Python 2.3(EE), Idle 1.0, PyCrust 0.7.2
                        Python 2.1.1 Idle 0.8
nt        win32         Windows 98, Python 2.1.1. Idle 0.8
nt        win32         Cygwin 98-4.10, Python 2.1.1(MSC) - echo tests
                        fail i.e. redefining environment variables may
                        not work. FIXED: don't use cygwin echo!
                        Comment: also `cmd /c echo` will not work
                        but redefining environment variables do work.
posix     cygwin        Cygwin 98-4.10, Python 2.3.3(cygming special)
nt        win32         Windows XP, Python 2.3.3
========  ============  =================================================

Known bugs:

* Tests, that send messages to stderr, fail when executed from MSYS prompt
  because the messages are lost at some point.

"""
__all__ = ['exec_command', 'find_executable']

import os  # 导入操作系统相关的功能
import sys  # 导入系统相关的功能
import subprocess  # 导入子进程管理的功能
import locale  # 导入处理本地化的功能
import warnings  # 导入警告处理的功能

from numpy.distutils.misc_util import is_sequence, make_temp_file  # 导入 numpy 相关的功能
from numpy.distutils import log  # 导入 numpy 相关的日志记录功能

def filepath_from_subprocess_output(output):
    """
    Convert `bytes` in the encoding used by a subprocess into a filesystem-appropriate `str`.

    Inherited from `exec_command`, and possibly incorrect.
    """
    mylocale = locale.getpreferredencoding(False)  # 获取首选编码
    if mylocale is None:
        mylocale = 'ascii'
    output = output.decode(mylocale, errors='replace')  # 解码 subprocess 输出为字符串
    output = output.replace('\r\n', '\n')  # 替换换行符格式
    # Another historical oddity
    if output[-1:] == '\n':  # 移除末尾可能存在的多余换行符
        output = output[:-1]
    return output

def forward_bytes_to_stdout(val):
    """
    Forward bytes from a subprocess call to the console, without attempting to
    decode them.
    """
    # 此函数用于将子进程调用的字节流直接输出到控制台,不进行解码操作
    # 假设 subprocess 调用已经返回了适当编码的字节流数据。
    if hasattr(sys.stdout, 'buffer'):
        # 如果 sys.stdout 有 'buffer' 属性,直接使用底层的二进制输出
        sys.stdout.buffer.write(val)
    elif hasattr(sys.stdout, 'encoding'):
        # 如果 sys.stdout 有 'encoding' 属性,尝试使用相同的编码进行解码和再编码
        sys.stdout.write(val.decode(sys.stdout.encoding))
    else:
        # 如果无法确定编码,使用 UTF-8 编码进行解码,替换错误的字符
        sys.stdout.write(val.decode('utf8', errors='replace'))
def temp_file_name():
    # 发出警告,提示 temp_file_name 函数在 NumPy v1.17 版本后已弃用,建议使用 tempfile.mkstemp 替代
    warnings.warn('temp_file_name is deprecated since NumPy v1.17, use '
                  'tempfile.mkstemp instead', DeprecationWarning, stacklevel=1)
    # 调用 make_temp_file 函数创建临时文件,返回文件对象和文件名
    fo, name = make_temp_file()
    # 关闭临时文件对象
    fo.close()
    # 返回临时文件名
    return name

def get_pythonexe():
    # 获取当前 Python 解释器的可执行文件路径
    pythonexe = sys.executable
    # 如果操作系统为 Windows 平台
    if os.name in ['nt', 'dos']:
        # 分离文件路径和文件名
        fdir, fn = os.path.split(pythonexe)
        # 将文件名转换为大写并替换 'PYTHONW' 为 'PYTHON'
        fn = fn.upper().replace('PYTHONW', 'PYTHON')
        # 拼接路径和修改后的文件名
        pythonexe = os.path.join(fdir, fn)
        # 断言文件路径存在且是一个文件
        assert os.path.isfile(pythonexe), '%r is not a file' % (pythonexe,)
    # 返回 Python 解释器的可执行文件路径
    return pythonexe

def find_executable(exe, path=None, _cache={}):
    """Return full path of a executable or None.

    Symbolic links are not followed.
    """
    # 以 (exe, path) 为键从缓存中查找路径
    key = exe, path
    try:
        return _cache[key]
    except KeyError:
        pass
    # 记录调试信息,查找可执行文件
    log.debug('find_executable(%r)' % exe)
    # 保存原始的可执行文件名
    orig_exe = exe

    # 如果路径为空,则使用环境变量 PATH 或者默认路径
    if path is None:
        path = os.environ.get('PATH', os.defpath)
    # 根据操作系统类型选择 realpath 函数
    if os.name=='posix':
        realpath = os.path.realpath
    else:
        realpath = lambda a:a

    # 如果可执行文件名以双引号开头,则去除双引号
    if exe.startswith('"'):
        exe = exe[1:-1]

    # Windows 平台的可执行文件后缀列表
    suffixes = ['']
    if os.name in ['nt', 'dos', 'os2']:
        fn, ext = os.path.splitext(exe)
        extra_suffixes = ['.exe', '.com', '.bat']
        # 如果文件名后缀不在附加后缀列表中,则使用附加后缀
        if ext.lower() not in extra_suffixes:
            suffixes = extra_suffixes

    # 如果可执行文件名是绝对路径
    if os.path.isabs(exe):
        paths = ['']
    else:
        # 将 PATH 分割为绝对路径列表
        paths = [ os.path.abspath(p) for p in path.split(os.pathsep) ]

    # 遍历所有可能的路径和后缀
    for path in paths:
        fn = os.path.join(path, exe)
        for s in suffixes:
            f_ext = fn+s
            # 如果文件不是符号链接,则获取其真实路径
            if not os.path.islink(f_ext):
                f_ext = realpath(f_ext)
            # 如果文件存在且可执行,则返回其路径
            if os.path.isfile(f_ext) and os.access(f_ext, os.X_OK):
                log.info('Found executable %s' % f_ext)
                _cache[key] = f_ext
                return f_ext

    # 记录警告信息,未找到可执行文件
    log.warn('Could not locate executable %s' % orig_exe)
    return None

############################################################

def _preserve_environment( names ):
    # 记录调试信息,保留环境变量
    log.debug('_preserve_environment(%r)' % (names))
    # 创建包含指定环境变量名及其当前值的字典
    env = {name: os.environ.get(name) for name in names}
    # 返回环境变量字典
    return env

def _update_environment( **env ):
    # 记录调试信息,更新环境变量
    log.debug('_update_environment(...)')
    # 遍历环境变量字典,更新当前进程的环境变量
    for name, value in env.items():
        os.environ[name] = value or ''

def exec_command(command, execute_in='', use_shell=None, use_tee=None,
                 _with_python = 1, **env ):
    """
    Return (status,output) of executed command.

    .. deprecated:: 1.17
        Use subprocess.Popen instead

    Parameters
    ----------
    command : str
        A concatenated string of executable and arguments.
    execute_in : str
        Before running command ``cd execute_in`` and after ``cd -``.
    use_shell : {bool, None}, optional
        If True, execute ``sh -c command``. Default None (True)
    use_tee : {bool, None}, optional
        If True use tee. Default None (True)


    Returns
    -------
    """
    res : str
        Both stdout and stderr messages.

    Notes
    -----
    On NT, DOS systems the returned status is correct for external commands.
    Wild cards will not work for non-posix systems or when use_shell=0.

    """
    # 发出警告,提示 exec_command 函数自 NumPy v1.17 起已废弃,请使用 subprocess.Popen 替代
    warnings.warn('exec_command is deprecated since NumPy v1.17, use '
                  'subprocess.Popen instead', DeprecationWarning, stacklevel=1)
    # 记录调试信息,显示执行的命令和环境变量
    log.debug('exec_command(%r,%s)' % (command,
         ','.join(['%s=%r'%kv for kv in env.items()])))

    # 根据操作系统类型决定是否使用 tee 命令
    if use_tee is None:
        use_tee = os.name=='posix'
    # 根据操作系统类型决定是否使用 shell
    if use_shell is None:
        use_shell = os.name=='posix'
    # 将执行路径转换为绝对路径
    execute_in = os.path.abspath(execute_in)
    # 获取当前工作目录的绝对路径
    oldcwd = os.path.abspath(os.getcwd())

    # 根据文件名是否包含 'exec_command' 来决定执行目录的设定
    if __name__[-12:] == 'exec_command':
        exec_dir = os.path.dirname(os.path.abspath(__file__))
    elif os.path.isfile('exec_command.py'):
        exec_dir = os.path.abspath('.')
    else:
        exec_dir = os.path.abspath(sys.argv[0])
        if os.path.isfile(exec_dir):
            exec_dir = os.path.dirname(exec_dir)

    # 如果旧工作目录与执行目录不同,则切换工作目录到执行目录,并记录调试信息
    if oldcwd!=execute_in:
        os.chdir(execute_in)
        log.debug('New cwd: %s' % execute_in)
    else:
        # 如果旧工作目录与执行目录相同,则记录调试信息
        log.debug('Retaining cwd: %s' % oldcwd)

    # 保存当前环境的关键部分,更新环境变量
    oldenv = _preserve_environment( list(env.keys()) )
    _update_environment( **env )

    try:
        # 执行命令,获取执行状态 st
        st = _exec_command(command,
                           use_shell=use_shell,
                           use_tee=use_tee,
                           **env)
    finally:
        # 如果旧工作目录与执行目录不同,则恢复工作目录到旧工作目录,并记录调试信息
        if oldcwd!=execute_in:
            os.chdir(oldcwd)
            log.debug('Restored cwd to %s' % oldcwd)
        # 恢复旧环境变量
        _update_environment(**oldenv)

    # 返回执行状态 st
    return st
# 执行给定命令的内部工作函数,用于 exec_command()。
def _exec_command(command, use_shell=None, use_tee=None, **env):
    # 如果 use_shell 未指定,则根据操作系统确定是否使用 shell
    if use_shell is None:
        use_shell = os.name == 'posix'
    # 如果 use_tee 未指定,则根据操作系统确定是否使用 tee
    if use_tee is None:
        use_tee = os.name == 'posix'

    # 在 POSIX 系统上且需要使用 shell 时,覆盖 subprocess 默认的 /bin/sh
    if os.name == 'posix' and use_shell:
        sh = os.environ.get('SHELL', '/bin/sh')
        # 如果命令是一个序列,则创建一个新的命令序列
        if is_sequence(command):
            command = [sh, '-c', ' '.join(command)]
        else:
            command = [sh, '-c', command]
        use_shell = False

    # 在 Windows 上且命令是一个序列时,手动拼接字符串以用于 CreateProcess()
    elif os.name == 'nt' and is_sequence(command):
        command = ' '.join(_quote_arg(arg) for arg in command)

    # 默认情况下继承环境变量
    env = env or None
    try:
        # 启动子进程执行命令,text 设为 False 以便 communicate() 返回字节流,
        # 我们需要手动解码输出,以避免遇到无效字符时引发 UnicodeDecodeError
        proc = subprocess.Popen(command, shell=use_shell, env=env, text=False,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
    except OSError:
        # 如果启动子进程失败,返回 127,并返回空字符串
        return 127, ''

    # 读取子进程的输出和错误信息
    text, err = proc.communicate()
    
    # 获取系统首选编码,用于解码子进程输出
    mylocale = locale.getpreferredencoding(False)
    if mylocale is None:
        mylocale = 'ascii'
    # 使用替换错误模式解码文本,将 '\r\n' 替换为 '\n'
    text = text.decode(mylocale, errors='replace')
    text = text.replace('\r\n', '\n')

    # 去除末尾的换行符(历史遗留问题)
    if text[-1:] == '\n':
        text = text[:-1]

    # 如果需要使用 tee,并且输出文本不为空,则打印输出文本
    if use_tee and text:
        print(text)

    # 返回子进程的返回码和处理后的输出文本
    return proc.returncode, text


# 将参数 arg 安全地引用为可以在 shell 命令行中使用的形式
def _quote_arg(arg):
    # 如果字符串中不包含双引号且包含空格,则将整个字符串用双引号引起来
    if '"' not in arg and ' ' in arg:
        return '"%s"' % arg
    return arg

.\numpy\numpy\distutils\extension.py

"""
distutils.extension

Provides the Extension class, used to describe C/C++ extension
modules in setup scripts.

Overridden to support f2py.

"""
# 导入正则表达式模块
import re
# 从distutils.extension模块导入Extension类,并起别名为old_Extension
from distutils.extension import Extension as old_Extension

# 定义一个正则表达式,匹配C++源文件的文件名后缀
cxx_ext_re = re.compile(r'.*\.(cpp|cxx|cc)\Z', re.I).match
# 定义一个正则表达式,匹配Fortran和Python语言接口文件的文件名后缀
fortran_pyf_ext_re = re.compile(r'.*\.(f90|f95|f77|for|ftn|f|pyf)\Z', re.I).match


class Extension(old_Extension):
    """
    Parameters
    ----------
    name : str
        Extension name.
    sources : list of str
        List of source file locations relative to the top directory of
        the package.
    extra_compile_args : list of str
        Extra command line arguments to pass to the compiler.
    extra_f77_compile_args : list of str
        Extra command line arguments to pass to the fortran77 compiler.
    extra_f90_compile_args : list of str
        Extra command line arguments to pass to the fortran90 compiler.
    """
    # 初始化函数,用于初始化一个扩展模块对象,设置各种编译和链接选项
    def __init__(
            self, name, sources,
            include_dirs=None,
            define_macros=None,
            undef_macros=None,
            library_dirs=None,
            libraries=None,
            runtime_library_dirs=None,
            extra_objects=None,
            extra_compile_args=None,
            extra_link_args=None,
            export_symbols=None,
            swig_opts=None,
            depends=None,
            language=None,
            f2py_options=None,
            module_dirs=None,
            extra_c_compile_args=None,
            extra_cxx_compile_args=None,
            extra_f77_compile_args=None,
            extra_f90_compile_args=None,):
    
        # 调用旧版本的 Extension 类的初始化函数,初始化基类
        old_Extension.__init__(
                self, name, [],
                include_dirs=include_dirs,
                define_macros=define_macros,
                undef_macros=undef_macros,
                library_dirs=library_dirs,
                libraries=libraries,
                runtime_library_dirs=runtime_library_dirs,
                extra_objects=extra_objects,
                extra_compile_args=extra_compile_args,
                extra_link_args=extra_link_args,
                export_symbols=export_symbols)
    
        # 将传入的 sources 参数赋值给当前对象的 sources 属性
        # 避免 assert 语句检查 sources 是否包含字符串类型
        self.sources = sources
    
        # 设置 swig_opts 属性,如果未指定则为空列表
        self.swig_opts = swig_opts or []
        # 如果 swig_opts 被指定为字符串而非列表,则进行警告,并将其转换为列表
        if isinstance(self.swig_opts, str):
            import warnings
            msg = "swig_opts is specified as a string instead of a list"
            warnings.warn(msg, SyntaxWarning, stacklevel=2)
            self.swig_opts = self.swig_opts.split()
    
        # 设置 depends 属性,默认为空列表
        self.depends = depends or []
        # 设置 language 属性
        self.language = language
    
        # 设置 f2py_options、module_dirs、extra_c_compile_args、extra_cxx_compile_args、
        # extra_f77_compile_args、extra_f90_compile_args 属性,默认均为空列表
        self.f2py_options = f2py_options or []
        self.module_dirs = module_dirs or []
        self.extra_c_compile_args = extra_c_compile_args or []
        self.extra_cxx_compile_args = extra_cxx_compile_args or []
        self.extra_f77_compile_args = extra_f77_compile_args or []
        self.extra_f90_compile_args = extra_f90_compile_args or []
    
        return

    # 判断当前模块是否包含 C++ 源文件
    def has_cxx_sources(self):
        # 遍历 sources 属性,判断是否包含 C++ 源文件的扩展名
        for source in self.sources:
            if cxx_ext_re(str(source)):
                return True
        return False

    # 判断当前模块是否包含用于 f2py 的源文件
    def has_f2py_sources(self):
        # 遍历 sources 属性,判断是否包含用于 f2py 的 Fortran pyf 文件
        for source in self.sources:
            if fortran_pyf_ext_re(source):
                return True
        return False
# 定义一个名为 Extension 的类
class Extension:

.\numpy\numpy\distutils\fcompiler\absoft.py

# 导入操作系统模块
import os

# 从 numpy.distutils.cpuinfo 模块导入 cpu 函数
# 从 numpy.distutils.fcompiler 模块导入 FCompiler 类和 dummy_fortran_file 函数
# 从 numpy.distutils.misc_util 模块导入 cyg2win32 函数
from numpy.distutils.cpuinfo import cpu
from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
from numpy.distutils.misc_util import cyg2win32

# 定义可用的编译器列表,其中只包含 AbsoftFCompiler
compilers = ['AbsoftFCompiler']

# 定义 AbsoftFCompiler 类,继承自 FCompiler
class AbsoftFCompiler(FCompiler):

    # 定义编译器类型为 'absoft'
    compiler_type = 'absoft'
    # 定义编译器描述
    description = 'Absoft Corp Fortran Compiler'
    # 定义版本模式匹配规则
    version_pattern = r'(f90:.*?(Absoft Pro FORTRAN Version|FORTRAN 77 Compiler|Absoft Fortran Compiler Version|Copyright Absoft Corporation.*?Version))'+\
                       r' (?P<version>[^\s*,]*)(.*?Absoft Corp|)'

    # 定义可执行文件字典
    executables = {
        'version_cmd'  : None,          # set by update_executables
        'compiler_f77' : ["f77"],
        'compiler_fix' : ["f90"],
        'compiler_f90' : ["f90"],
        'linker_so'    : ["<F90>"],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }

    # 如果操作系统为 Windows
    if os.name=='nt':
        # 定义库开关为 '/out:'
        library_switch = '/out:'      #No space after /out:!

    # 定义模块目录开关为空
    module_dir_switch = None
    # 定义模块包含开关为 '-p'
    module_include_switch = '-p'
    
    # 定义更新可执行程序的方法
    def update_executables(self):
        # 调用 cyg2win32 函数,并传入虚拟的 Fortran 文件名,更新版本命令为 ['<F90>', '-V', '-c', f+'.f', '-o', f+'.o']

    # 定义获取链接器选项的方法
    def get_flags_linker_so(self):
        # 如果操作系统为 Windows
        if os.name=='nt':
            # 定义选项为 ['/dll']
        # 如果版本大于等于 9.0
        elif self.get_version() >= '9.0':
            # 定义选项为 ['-shared']
        else:
            # 定义选项为 ["-K", "shared"]
        # 返回选项

    # 定义库目录选项的方法
    def library_dir_option(self, dir):
        # 如果操作系统为 Windows
        if os.name=='nt':
            # 返回 ['-link', '/PATH:%s' % (dir)]
        # 返回 "-L" + dir

    # 定义库选项的方法
    def library_option(self, lib):
        # 如果操作系统为 Windows
        if os.name=='nt':
            # 返回 '%s.lib' % (lib)
        # 返回 "-l" + lib
    def get_library_dirs(self):
        # 调用父类的方法获取库目录列表
        opt = FCompiler.get_library_dirs(self)
        # 获取环境变量ABSOFT的值
        d = os.environ.get('ABSOFT')
        # 如果存在ABSOFT环境变量
        if d:
            # 获取版本号并判断是否大于等于10.0
            if self.get_version() >= '10.0':
                # 使用共享库,静态库未使用-fPIC编译
                prefix = 'sh'
            else:
                prefix = ''
            # 判断CPU是否为64位
            if cpu.is_64bit():
                suffix = '64'
            else:
                suffix = ''
            # 将目录添加到库目录列表
            opt.append(os.path.join(d, '%slib%s' % (prefix, suffix)))
        return opt

    def get_libraries(self):
        # 调用父类的方法获取库列表
        opt = FCompiler.get_libraries(self)
        # 获取版本号并根据版本号添加不同的库
        if self.get_version() >= '11.0':
            opt.extend(['af90math', 'afio', 'af77math', 'amisc'])
        elif self.get_version() >= '10.0':
            opt.extend(['af90math', 'afio', 'af77math', 'U77'])
        elif self.get_version() >= '8.0':
            opt.extend(['f90math', 'fio', 'f77math', 'U77'])
        else:
            opt.extend(['fio', 'f90math', 'fmath', 'U77'])
        # 如果操作系统为Windows,添加COMDLG32库
        if os.name =='nt':
            opt.append('COMDLG32')
        return opt

    def get_flags(self):
        # 调用父类的方法获取编译选项列表
        opt = FCompiler.get_flags(self)
        # 如果操作系统不是Windows,添加'-s'选项,并根据版本号添加不同的选项
        if os.name != 'nt':
            opt.extend(['-s'])
            if self.get_version():
                if self.get_version()>='8.2':
                    opt.append('-fpic')
        return opt

    def get_flags_f77(self):
        # 调用父类的方法获取Fortran 77编译选项列表
        opt = FCompiler.get_flags_f77(self)
        # 添加特定的编译选项
        opt.extend(['-N22', '-N90', '-N110'])
        v = self.get_version()
        # 如果操作系统为Windows,并且版本号大于等于8.0,添加特定的编译选项
        if os.name == 'nt':
            if v and v>='8.0':
                opt.extend(['-f', '-N15'])
        else:
            opt.append('-f')
            # 根据版本号添加不同的编译选项
            if v:
                if v<='4.6':
                    opt.append('-B108')
                else:
                    opt.append('-N15')
        return opt

    def get_flags_f90(self):
        # 调用父类的方法获取Fortran 90编译选项列表
        opt = FCompiler.get_flags_f90(self)
        # 添加特定的编译选项
        opt.extend(["-YCFRL=1", "-YCOM_NAMES=LCS", "-YCOM_PFX", "-YEXT_PFX",
                    "-YCOM_SFX=_", "-YEXT_SFX=_", "-YEXT_NAMES=LCS"])
        # 如果有版本号,根据版本号添加不同的编译选项
        if self.get_version():
            if self.get_version()>'4.6':
                opt.extend(["-YDEALLOC=ALL"])
        return opt

    def get_flags_fix(self):
        # 调用父类的方法获取固定格式编译选项列表
        opt = FCompiler.get_flags_fix(self)
        # 添加特定的编译选项
        opt.extend(["-YCFRL=1", "-YCOM_NAMES=LCS", "-YCOM_PFX", "-YEXT_PFX",
                    "-YCOM_SFX=_", "-YEXT_SFX=_", "-YEXT_NAMES=LCS"])
        opt.extend(["-f", "fixed"])
        return opt

    def get_flags_opt(self):
        # 返回优化编译选项列表
        opt = ['-O']
        return opt
# 如果当前模块作为脚本直接执行
if __name__ == '__main__':
    # 从 distutils 模块导入 log
    from distutils import log
    # 设置日志记录级别为 2
    log.set_verbosity(2)
    # 从 numpy.distutils 模块导入 customized_fcompiler
    from numpy.distutils import customized_fcompiler
    # 打印使用 absoft 编译器的版本信息
    print(customized_fcompiler(compiler='absoft').get_version())

.\numpy\numpy\distutils\fcompiler\arm.py

# 导入所需模块和库
import sys
from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
from sys import platform
from os.path import join, dirname, normpath

# 定义 ArmFlangCompiler 类,继承自 FCompiler 类
class ArmFlangCompiler(FCompiler):
    # 定义编译器类型和描述
    compiler_type = 'arm'
    description = 'Arm Compiler'
    version_pattern = r'\s*Arm.*version (?P<version>[\d.-]+).*'

    # 定义一些可执行文件和命令
    ar_exe = 'lib.exe'
    possible_executables = ['armflang']
    executables = {
        'version_cmd': ["", "--version"],
        'compiler_f77': ["armflang", "-fPIC"],
        'compiler_fix': ["armflang", "-fPIC", "-ffixed-form"],
        'compiler_f90': ["armflang", "-fPIC"],
        'linker_so': ["armflang", "-fPIC", "-shared"],
        'archiver': ["ar", "-cr"],
        'ranlib':  None
    }
    
    # 定义一些编译器选项和方法
    pic_flags = ["-fPIC", "-DPIC"]
    c_compiler = 'arm'
    module_dir_switch = '-module '  # 不要删除结尾的空格!

    # 定义获取库的方法
    def get_libraries(self):
        opt = FCompiler.get_libraries(self)
        opt.extend(['flang', 'flangrti', 'ompstub'])
        return opt
    
    # 定义获取库目录的方法
    @functools.lru_cache(maxsize=128)
    def get_library_dirs(self):
        """List of compiler library directories."""
        opt = FCompiler.get_library_dirs(self)
        flang_dir = dirname(self.executables['compiler_f77'][0])
        opt.append(normpath(join(flang_dir, '..', 'lib')))
        return opt
    
    # 定义获取编译器标志的方法
    def get_flags(self):
        return []

    # 定义获取自由编译器标志的方法
    def get_flags_free(self):
        return []

    # 定义获取调试编译器标志的方法
    def get_flags_debug(self):
        return ['-g']

    # 定义获取优化编译器标志的方法
    def get_flags_opt(self):
        return ['-O3']

    # 定义获取体系结构编译器标志的方法
    def get_flags_arch(self):
        return []

    # 定义运行时库目录选项的方法
    def runtime_library_dir_option(self, dir):
        return '-Wl,-rpath=%s' % dir

# 如果作为主程序运行,则执行以下代码
if __name__ == '__main__':
    # 导入所需模块和库
    from distutils import log
    log.set_verbosity(2)
    from numpy.distutils import customized_fcompiler
    # 打印定制的编译器版本信息
    print(customized_fcompiler(compiler='armflang').get_version())

.\numpy\numpy\distutils\fcompiler\compaq.py

# 导入操作系统和系统模块
import os
import sys

# 从numpy.distutils.fcompiler模块中导入FCompiler类和DistutilsPlatformError异常
from numpy.distutils.fcompiler import FCompiler
from distutils.errors import DistutilsPlatformError

# 定义编译器列表
compilers = ['CompaqFCompiler']
# 检查操作系统是否为posix,或者sys.platform是否以'cygwin'开头,如果是则添加'CompaqVisualFCompiler'到编译器列表中
if os.name != 'posix' or sys.platform[:6] == 'cygwin' :
    # 否则在类别系统(如darwin)上会出现误报,因为会选择/bin/df
    compilers.append('CompaqVisualFCompiler')

# 定义CompaqFCompiler类,继承自FCompiler类
class CompaqFCompiler(FCompiler):

    # 设置编译器类型和描述
    compiler_type = 'compaq'
    description = 'Compaq Fortran Compiler'
    version_pattern = r'Compaq Fortran (?P<version>[^\s]*).*'

    # 如果操作系统是linux,则设置fc_exe为'fort';否则为'f90'
    if sys.platform[:5]=='linux':
        fc_exe = 'fort'
    else:
        fc_exe = 'f90'

    # 定义各种可执行文件的命令
    executables = {
        'version_cmd'  : ['<F90>', "-version"],
        'compiler_f77' : [fc_exe, "-f77rtl", "-fixed"],
        'compiler_fix' : [fc_exe, "-fixed"],
        'compiler_f90' : [fc_exe],
        'linker_so'    : ['<F90>'],
        'archiver'     : ["ar", "-cr"],
        'ranlib'       : ["ranlib"]
        }

    # 设置模块目录和模块引入开关(未经测试)
    module_dir_switch = '-module ' 
    module_include_switch = '-I'

    # 定义获取编译器标志、调试标志、优化标志和架构标志的方法
    def get_flags(self):
        return ['-assume no2underscore', '-nomixed_str_len_arg']
    def get_flags_debug(self):
        return ['-g', '-check bounds']
    def get_flags_opt(self):
        return ['-O4', '-align dcommons', '-assume bigarrays',
                '-assume nozsize', '-math_library fast']
    def get_flags_arch(self):
        return ['-arch host', '-tune host']
    def get_flags_linker_so(self):
        if sys.platform[:5]=='linux':
            return ['-shared']
        return ['-shared', '-Wl,-expect_unresolved,*']

# 定义CompaqVisualFCompiler类,继承自FCompiler类
class CompaqVisualFCompiler(FCompiler):

    # 设置编译器类型和描述
    compiler_type = 'compaqv'
    description = 'DIGITAL or Compaq Visual Fortran Compiler'
    version_pattern = (r'(DIGITAL|Compaq) Visual Fortran Optimizing Compiler'
                       r' Version (?P<version>[^\s]*).*')

    compile_switch = '/compile_only'
    object_switch = '/object:'
    library_switch = '/OUT:'      #No space after /OUT:!

    static_lib_extension = ".lib"
    static_lib_format = "%s%s"
    module_dir_switch = '/module:'
    module_include_switch = '/I'

    ar_exe = 'lib.exe'
    fc_exe = 'DF'

    # 如果操作系统是'win32',则从numpy.distutils.msvccompiler模块中导入MSVCCompiler类,并尝试获取其lib属性
    if sys.platform=='win32':
        from numpy.distutils.msvccompiler import MSVCCompiler
        try:
            m = MSVCCompiler()
            m.initialize()
            ar_exe = m.lib
        except DistutilsPlatformError:
            pass
        except AttributeError as e:
            if '_MSVCCompiler__root' in str(e):
                print('Ignoring "%s" (I think it is msvccompiler.py bug)' % (e))
            else:
                raise
        except OSError as e:
            if not "vcvarsall.bat" in str(e):
                print("Unexpected OSError in", __file__)
                raise
        except ValueError as e:
            if not "'path'" in str(e):
                print("Unexpected ValueError in", __file__)
                raise
    # 定义包含不同命令和参数的可执行文件的字典
    executables = {
        'version_cmd'  : ['<F90>', "/what"],  # 版本命令,包含<F90>和/what参数
        'compiler_f77' : [fc_exe, "/f77rtl", "/fixed"],  # F77编译器,包含fc_exe、/f77rtl和/fixed参数
        'compiler_fix' : [fc_exe, "/fixed"],  # fix编译器,包含fc_exe和/fixed参数
        'compiler_f90' : [fc_exe],  # F90编译器,包含fc_exe参数
        'linker_so'    : ['<F90>'],  # 共享库链接器,包含<F90>参数
        'archiver'     : [ar_exe, "/OUT:"],  # 静态库创建工具,包含ar_exe和/OUT:参数
        'ranlib'       : None  # ranlib为空
        }

    # 获取编译器的标志列表
    def get_flags(self):
        return ['/nologo', '/MD', '/WX', '/iface=(cref,nomixed_str_len_arg)',  
                '/names:lowercase', '/assume:underscore']
    # 获取优化编译器的标志列表
    def get_flags_opt(self):
        return ['/Ox', '/fast', '/optimize:5', '/unroll:0', '/math_library:fast']
    # 获取架构编译器的标志列表
    def get_flags_arch(self):
        return ['/threads']
    # 获取调试编译器的标志列表
    def get_flags_debug(self):
        return ['/debug']
# 检查当前模块是否是主程序
if __name__ == '__main__':
    # 从 distutils 模块导入 log 功能
    from distutils import log
    # 设置 log 的输出级别为 2
    log.set_verbosity(2)
    # 从 numpy.distutils 模块导入 customized_fcompiler 功能
    from numpy.distutils import customized_fcompiler
    # 输出使用 compaq 编译器的版本信息
    print(customized_fcompiler(compiler='compaq').get_version())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值