主页

索引

模块索引

搜索页面

1.3.5. 模块加载

备注

相关参考: pep 420

模块

模块通常为单独的.py文件,可以用import直接引用,可以作为模块的文件类型有:

.py、.pyo、.pyc、.pyd、.so、.dll

几种导入方式:

import subpackage1.a
    # 将模块subpackage.a导入全局命名空间,例如访问a中属性时用subpackage1.a.attr
from subpackage1 import a
    # 将模块a导入全局命名空间,例如访问a中属性时用a.attr_a
from subpackage.a import attr_a
    # 将模块a的属性直接导入到命名空间中,例如访问a中属性时直接用attr_a

重要

模块搜索路径(import命令)的第一个条目:如果存在输入脚本的话,是包含输入脚本的目录。 否则,第一个条目将是当前目录,当执行交互式 shell, -c 命令, 或 -m 模块时都属于这种情况。python 程序运行时,考虑相对路径时,考虑的是``运行文件所在目录``的相对路径,而``不是工作目录``的路径。

重要

sys.path 是``相对工作目录``而言的,而不是``相对文件所在目录``。因此我们在当前目录运行时:使用``sys.append(‘..’)``;在父目录运行程序,工作目录变化了,使用``sys.append(‘.’)``

__init__.py文件

  • python3中,有没有``__init__.py``文件程序都能正常导入运行

  • python2中,没有``__init__.py``的话则不能导入moda.py模块下的funa函数

导入需要的模块

my_package/__init__.py 中,输入以下代码:

from .file1 import func_1
from .file2 import func_2

在package目录下,创建1个 main.py

import my_package  # this imports the entire module

# 调用
my_package.func_1()
my_package.func_2()

设置 __all__ 参数

  • 如果 __init__.py中设置__all__ 列表变量, 则 from package import * 语句导入__all__中包含的所有模块或全局变量。

__init__.py 代码:

__all__ = ["func_1", "func_2", "func_3"]

然后在 main.py 中:

from my_package import * # 执行时,最终只有3个模块被导入
func_1()
func_2()
func_3()

警告

在实际编写代码时,尽量不要用import * 来导入包中所有模块与全局变量,以避免未知的命名冲突。

导入子目录下的包

  • 如果想直接import包(package)中的方法,而不是import包下模块(module)中的方法,就需要在 __init__.py 文件中先引入

直接运行 和 模块运行

  • 直接运行: python folder/module.py (sys.path 指的是运行文件对应的目录)

  • 模块运行: python -m folder.module (sys.path 指的是当前运行目录)

备注

详细验证文件参见: demo-python 项目中的 0module_loading

示例讲解

项目结构:

statistics
    ->activity
        -> stat.py
    ->base
        ->connection.py
        ->__init__.py

直接运行的情况

  • 如果我们想在stat.py 里面import activity目录上一个文件夹的其他模块是不可以的

  • 比如我想导入base.connection里面的db_mongo, 这是不可以的

  • 因为sys.path 就是在activity目录,根目录statictis 没有在sys.path里面

    from base.connection import db_mongo 会报错: ImportError: No module named base.connection

通过相对路径引入(直接执行py文件的话,是不可以使用相对引入的):

from ..base.connection import db_mongo
报另外一个报错:
ValueError: Attempted relative import in non-package

用模块运行的情况

from base.connection import db_mongo

ValueError: Attempted relative import beyond toplevel package

PYTHONPATH环境变量

默认情况:

$ echo $PYTHONPATH
$ python
>>> import sys
>>> sys.path
['', ...]

指定PYTHONPATH:

$ export PYTHONPATH=/home/zhaoweiguo/lib
$ python
>>> import sys
>>> sys.path
['', '/home/zhaoweiguo/lib', ...]

The Module Search Path

the interpreter:

1. searche for a `built-in module` with that name
    sys.builtin_module_names
2. searches for a file named xxxx.py in a list of directories given by the variable `sys.path`
    sys.path

sys.builtin_module_names:

('_abc',
 '_ast',
 '_codecs',
 '_collections',
 '_functools',
 '_imp',
 '_io',
 '_locale',
 '_operator',
 '_peg_parser',
 '_signal',
 '_sre',
 '_stat',
 '_string',
 '_symtable',
 '_thread',
 '_tracemalloc',
 '_warnings',
 '_weakref',
 'atexit',
 'builtins',
 'errno',
 'faulthandler',
 'gc',
 'itertools',
 'marshal',
 'posix',
 'pwd',
 'sys',
 'time',
 'xxsubtype')

sys.path:

['/data/anaconda3/envs/<name>/bin',
 '/data/anaconda3/envs/<name>/lib/python39.zip',
 '/data/anaconda3/envs/<name>/lib/python3.9',
 '/data/anaconda3/envs/<name>/lib/python3.9/lib-dynload',
 '',
 '/data/anaconda3/envs/<name>/lib/python3.9/site-packages']

示例

示例2

加载上级目录的库文件:

import sys
sys.path.append('..')
from common.utils import load_data

修改库文件后重新加载:

import importlib
from common import utils
importlib.reload(utils)

# 重新导入修改后的函数
from common.utils import mape

主页

索引

模块索引

搜索页面