Python:加载os和os.path之间的关联和区别

Python:os和os.path之间的关联和区别

在讲加载之前,要讲一个sys模块的modules用法的意义:

import sys

print(sys.modules)

sys.modules返回的是一个字典,里面包含着当前系统运行之前预加载的一些基础模块,key是名字,value是指向模块实际存放的位置。

os和os.path的区别:

import os
import os.path

一,import os时,就会去找sys.modules当前系统是否已经加载,如果已经加载就不会再次导入模块了

二,import os.path:我们知道Python中import后面必须是一个模块名,但是这里os.path你在Python的模块目录中是找不到这个叫path.py这个名字的文件。
Python3.6.4 os模块的一段源码:

_names = sys.builtin_module_names

# Note:  more names are added to __all__ later.
__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
           "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR",
           "SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen",
           "popen", "extsep"]

def _exists(name):
    return name in globals()

def _get_exports_list(module):
    try:
        return list(module.__all__)
    except AttributeError:
        return [n for n in dir(module) if n[0] != '_']

# Any new dependencies of the os module and/or changes in path separator
# requires updating importlib as well.
if 'posix' in _names:
    name = 'posix'
    linesep = '\n'
    from posix import *
    try:
        from posix import _exit
        __all__.append('_exit')
    except ImportError:
        pass
    import posixpath as path

    try:
        from posix import _have_functions
    except ImportError:
        pass

    import posix
    __all__.extend(_get_exports_list(posix))
    del posix

elif 'nt' in _names:
    name = 'nt'
    linesep = '\r\n'
    from nt import *
    try:
        from nt import _exit
        __all__.append('_exit')
    except ImportError:
        pass
    import ntpath as path

    import nt
    __all__.extend(_get_exports_list(nt))
    del nt

    try:
        from nt import _have_functions
    except ImportError:
        pass

else:
    raise ImportError('no os specific module found')

sys.modules['os.path'] = path
from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
    devnull)

del _names

从这段源码中分析我们可以得出为什么有path这个模块!
一,在启动Python解释器时,Python会预先装在一些基本的模块,如os、sys等;在装载os模块时,程序也是从模块的开始一直读取运行到文件的结尾。
1,在开始时,程序把当前sys.builtin_module_names系统的一些信息收集起来返回一个元组,并打一个标签叫_names;
2,接下来通过if语句判断当前操作系统遵循什么标准开发的,如linux是Posix,Windows是NT;
3,根据判断加载相应的模块并as给一个新的名字path;到这里我们就拿到path,path只是对应加载模块的别名
4,到这里为止,我们并不能通过os模块中提供的all中的path来直接 import os.path

import posixpath as path
import ntpath as path

总结:
os和os.path两个模块在解释器运行之前已经加载,这些只是相当于名称,通过字典类型,指向真正的模块位置。

所以path其实不是os的子模块,这样理解是错误的。

os和os.path的关联:
问题:如果说path不是os的子模块,为什么我们能通过from os.path import exists?
1,在解释器运行之前会预先加载一些必要的模块,如os,再通过源码来理解。
2,加载os的判断当前系统是什么标准的,并加载真正的模块并as命名path
3,接下来看os源码中的这段代码

sys.modules['os.path'] = path

sys.modules:指的是当前解释器运行中加载的模块,以字典类型表示。
这段代码什么意思?

  1. 在当前解释器运行环境中加入一个key-value,key就是名称,value就是path,而path是上一段if else代码判断需要加载模块别名,是个对象(模块的位置)
  2. 所以我们能通过from os.path import exists执行成功

总结:

  1. Python解释器运行会预先加载一些基础模块,可以通过sys.modules查看
  2. 之所以能够通过from os.path import exists,是因为os.path是一个整体名称指向了一个模块。
  3. 同时os.path在解释器运行时有,是因为加载了os,os中定义os.path。

你可能感兴趣的:(Python)