import绝对是我们在使用python时最常用的语句之一了,但其实关于import,需要注意的地方还真不少,如导入第三方库,导入自己写的库,导入相对路径下文件中的方法,在包内部的相对与绝对导入等导入源;有导入的顺序;有Lazy Load惰性导入方法;有已经导入后的重载等等。本文就旨在讲清楚这些问题,并提供足够的示例以供参考。

Import已安装的第三方库

import

import as

from import

from import *

from . import *

import相对路径下的文件(非package)

只能引用本目录下的,子目录,孙目录等下的文件,不能引用父目录中的内容。

√ 以下是正确的:

import

from import

from

from .. import

× 以下是错误的:

import .

from . import

from . import

from .. import

当希望import非这些路径下的文件时:

先把这些文件的父文件夹append到sys.path中,然后直接import它们的名字。

import sys

sys.path.append()

import

在package内部import包相对路径下的文件

包其实可以看作是一种特殊的模块。例如常规包的目录中需要包含 __init__.py 文件,当包被导入时,该文件的顶层代码被隐式执行,就如同模块导入时顶层代码被执行,该文件就像是包的代码一样。所以 包是一种特殊的模块。需要记住的是,所有的包都是模块,但不是所有的模块都是包。包中子包和模块都有 __path__ 属性,具体地说,任何包含 __path__ 属性的模块被认为是包。所有的模块都有一个名称,类似于标准属性访问语法,子包与他们父包的名字之间用点隔开。

所有含有包内引用的脚本都不能直接被运行(python .py),而只能作为包的一部分被导入包外部的其他文件中使用(如from mlib.xxx.xxx import xxx)这里以包名字为mlib为例:

绝对路径引用

import mlib.

import mlib.

from mlib. import

相对路径引用

import .

import ..

import ..

from . import

from .

from ..

× 错误引用

import

from import

若想运行包内某个含有包引用的(相对或绝对都算)脚本:首先,不论如何,你不能试着在包内部目录下运行这个脚本。也就是说,如果你的包叫mlib,那你需要先在命令行中cd到其外部文件夹,只要不在包内,其他哪里都行。

python -m , 如:python -m ./mlib/utils/test.py。-m flag允许了用户运行包内部的python脚本。

但注意,即使是这样,依然有一定可能出现相对导入的问题,这个要视具体情况而定。

Lazy Load

如果你不一定会用到某个模块,但后续开发时候又很可能会用到他们,而你既不想每次都手动import, 又不想一次性导入一大堆可能使用的package,有没有解决方案?

还真有!这时候lazy load将是一个很好的选择。

下面是一份TensorFlow中包含的 Lazy Load 的代码。它可以做到并不真正import一个包,但在用户真正调用该包、该包的子模块,或是使用Tab自动补全时候把它真正导入。

代码

import importlib

import types

class LazyLoader(types.ModuleType):

"""Lazily import a module, mainly to avoid pulling in large dependencies.​`contrib`, and `ffmpeg` are examples of modules that are large and not alwaysneeded, and this allows them to only be loaded when they are used."""

def __init__(self, local_name, parent_module_globals, name):

self._local_name = local_name

self._parent_module_globals = parent_module_globals

super(LazyLoader, self).__init__(name)

def _load(self):

# Import the target module and insert it into the parent's namespace

module = importlib.import_module(self.__name__)

self._parent_module_globals[self._local_name] = module

# Update this object's dict so that if someone keeps a reference to the

# LazyLoader, lookups are efficient (__getattr__ is only called on lookups

# that fail).

self.__dict__.update(module.__dict__)

return module

def __getattr__(self, item):

module = self._load()

return getattr(module, item)

def __dir__(self):

module = self._load()

return dir(module)

使用方法:

from import LazyLoader

os = LazyLoader("os", globals(), "os")

op = LazyLoader("op", globals(), "os.path")

np = LazyLoader("np", globals(), "numpy")

或是如果你想更加优雅地一次性导入多个包而不用写N行重复代码:

_import_dict = {

"os": "os",

"sys": "sys",

"time": "time",

"math": "math",

"yaml": "yaml",

"random": "random",

"op": "os.path",

"np": "numpy",

"pd": "pandas",

"pkl": "pickle",

"glob": "glob",

"pf": "mlib.file.path_func",

"lang": "mlib.lang"

}

for key, value in _import_dict.items():

exec(f"{key}=LazyLoader('{key}', globals(), '{value}')")

你可以自定义你常用的一些模块和它们的简称,然后每次直接调用这份代码即可做到迅速而无痛import。

Re-import

如果你已经load了一个模块,但是由对这个模块本身的代码做出了修改,此时你也许就需要reload了,尤其是在jupyter环境下,这将是非常有用的功能。

import

from importlib import reload

reload()

在代码中通过包的字符串名称导入包

__import__或importlib.__import__都可以完成该任务,二者完全等价,但根据python官方文档建议,个人在代码中最好不要使用这个函数,而是使用其替代品importlib.import_module(name)。

__import__

__import__(name[, globals[, locals[, fromlist[, level]]]])

参数介绍:name (required): 被加载 module 的名称

globals (optional): 包含全局变量的字典,该选项很少使用,采用默认值 global()

locals (optional): 包含局部变量的字典,内部标准实现未用到该变量,采用默认值 - local()

fromlist (Optional): 被导入的 submodule 名称

level (Optional): 导入路径选项,Python 2 中默认为 -1,表示同时支持 absolute import 和 relative import。Python 3 中默认为 0,表示仅支持 absolute import。如果大于 0,则表示相对导入的父目录的级数,即 1 类似于 ‘.’,2 类似于 ‘..’。

使用示例:

# import spam

spam = __import__('spam')

# import spam.ham

spam = __import__('spam.ham')

# from spam.ham import eggs, sausage as saus

_temp = __import__('spam.ham', fromlist=['eggs', 'sausage'])

eggs = _temp.eggs

saus = _temp.sausage

import_module

importlib.import_module(name, package=None)

它最大的优点是方便,易于控制,与常见的import语法几乎完全一致,且支持绝对和相对import。例如:basic=importlib.import_module(".utils.basic", "mlib")。注意当name为相对路径时,package需要指定其父模块。Import a module. The name argument specifies what module to import in absolute or relative terms (e.g. either pkg.mod or ..mod). If the name is specified in relative terms, then the package argument must be set to the name of the package which is to act as the anchor for resolving the package name (e.g. import_module('..mod', 'pkg.subpkg') will import pkg.mod).

The pkg.mod), while pkg).

If you are dynamically importing a module that was created since the interpreter began execution (e.g., created a Python source file), you may need to call

Import的顺序

加载python时默认导入的标准库 > 同级目录下的文件(程序根目录) > PYTHONPATH环境变量设置的目录 > 标准库 > 第三方库

关于第一个“加载python时默认导入的标准库 ”,可以参见这篇文章中的解释。

Reference

python import_Python Import 详解相关推荐

  1. python读取word详解【from docx import Document】

    python读取word详解[from docx import Document] 目录 python读取word详解[from docx import Document] 前言 环境 示例字符串 下 ...

  2. Python字符编码详解

    Python字符编码详解 转自http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html Python字符编码详解 本文简单介绍了各种常用的 ...

  3. windows上安装Anaconda和python的教程详解

    一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因 ...

  4. python安装教程windows-windows上安装Anaconda和python的教程详解

    一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因 ...

  5. 代码检查规则:Python语言案例详解

    在之前的文章中代码检查规则:Java语言案例详解学习了Java的检查规则.我们今天将学习<代码检查规则:Python语言案例详解>,内容主要分为两个部分:Python的代码检查规则和Pyt ...

  6. python time模块详解

    python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明    一.简 ...

  7. Python 装饰器详解(上)

    Python 装饰器详解(上) 转自:https://blog.csdn.net/qq_27825451/article/details/84396970,博主仅对其中 demo 实现中不适合pyth ...

  8. python数值转换机_用于ETL的Python数据转换工具详解

    ETL的考虑 做 数据仓库系统,ETL是关键的一环.说大了,ETL是数据整合解决方案,说小了,就是倒数据的工具.回忆一下工作这么些年来,处理数据迁移.转换的工作倒 还真的不少.但是那些工作基本上是一次 ...

  9. 7、【转载】python yield generator 详解

    7.[转载]python yield generator 详解 目录 generator基础 generator应用 generator基础应用 generator高级应用 注意事项: 正文 本文将由 ...

最新文章

  1. django报错:django.db.utils.OperationalError: no such table:
  2. 如何更好的利用Node.js的性能极限
  3. Java,Math类中的ceil、floor和round函数源码解析以及自己重写实现
  4. linux网络保存退出,linux编辑文件后如何保存退出
  5. JLabel跟label
  6. .NET 4.5 Task异步编程学习资料
  7. android 获取monkey日志_Android压力测试:monkey压力测试实战
  8. android so abi适配,Android NDK学习(六): so文件兼容之abiFilters的使用
  9. Node.js笔记-node.js连接MySQL与增删改查
  10. BZOJ5073 小A的咒语(动态规划)
  11. 类的垂直关系中,如何把握纯虚函数
  12. Java中的java.util包
  13. 网页截图插件FireShot
  14. 论语之泰伯第八、子罕第九、乡党第十
  15. 银行卡号码校验算法(Luhn算法,又叫模10算法)
  16. MySQL锁 —— 记录锁、间隙锁、临键锁、自增锁
  17. typescript常用的一些内置类型
  18. MySQL 不等于null或空格
  19. 华为交换机配置SSH
  20. 一次腾讯云centos服务器被入侵的处理

热门文章

  1. 用7*7的卷积核分类9*9的图片到底应该用几个卷积核?55个
  2. android到顶部,Android recyclerview滚动到顶部
  3. 【Matlab】绘制3D 3维图
  4. 【数理知识】《矩阵论》方保镕老师-第2章-\lambda 矩阵与 Jordan 标准形
  5. 3.3 超参数训练实战:Pandas vs. Caviar-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  6. 8.2 高斯分布模型-机器学习笔记-斯坦福吴恩达教授
  7. Windows电脑C盘老是报红
  8. 把DXF导入到Altium Designer的完美方法
  9. 验证STIL的pattern的输入输出顺序
  10. 设计案例——点和圆的关系