关于 Python 的 import
好久以前就被 Python 的相对与绝对导入所困扰。去年粗浅探究后自以为完全理解,近来又因 sys.path[0]
和 os.getcwd()
的不一致而刷新了认知...
Python 官方文档 5. The import system — Python 3.10.5 documentation 当然是最好的学习指南,但全部看完对我来说还是有点难度。这里只选择一些要点讨论。
from import
import A
、import A as B
、from A import B
结构中,A
最小只能到 module。因此,只有使用 from import
结构才可以单独获取 module 里的属性。另外,相对引用必须使用 from import
结构。
from module import *
将导入 module
中的所有成员(有单双下划线前导的成员除外)。对于 package 可在 __init__.py
中定义 __all__ = ["module", "module", ...]
来手动控制的实际导入内容。
Package 与 __init__.py
Python 3.3 以后的 package 不再硬性需要 __init__.py
,普通文件夹等同于 __init__.py
留空的 namespace package。(关于 regular package 和 namespace package 的区别,参见 5. The import system — Python 3.10.5 documentation)
__init__.py
的作用在于当我们直接导入一个 package 的时候,实际上是执行了 __init__.py
。换句话说,直接导入一个 package 就是把它看做一个逻辑写在 __init__.py
里的 module。
需要注意的是,对于形如 A.B.C
的导入,A
、A.B
、A.B.C
对应的 __init__.py
都会被执行。也就是说,只要导入路径经过该 package,该 package 的 __init__.py
就会被执行。
Submodules
When a submodule is loaded using any mechanism (e.g.
importlib
APIs, theimport
orimport-from
statements, or built-in__import__()
) a binding is placed in the parent module’s namespace to the submodule object. For example, if packagespam
has a submodulefoo
, after importingspam.foo
,spam
will have an attributefoo
which is bound to the submodule....
Given Python’s familiar name binding rules this might seem surprising, but it’s actually a fundamental feature of the import system. The invariant holding is that if you have
sys.modules['spam']
andsys.modules['spam.foo']
(as you would after the above import), the latter must appear as thefoo
attribute of the former.
这是说,import 进来的 module 会被挂载到本 module 上作为其属性。
这个性质可以弄出来很多看上去很奇怪的玩意儿,比如说自己导入自己后可以 me.me.me.me...
无限嵌套之类的...
另外,对于形如 import A.B.C
的导入,A
、A.B
、A.B.C
都会被挂载到本 module 上。然而,from A.B import C
却只会挂载 C
,而 import A.B.C as D
也只会挂载 D
,即使 A
、A.B
都被执行且都在 sys.modules
里。
sys.path
A list of strings that specifies the search path for modules. Initialized from the environment variable
PYTHONPATH
, plus an installation-dependent default.As initialized upon program startup, the first item of this list,
path[0]
, is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input),path[0]
is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result ofPYTHONPATH
.A program is free to modify this list for its own purposes. Only strings and bytes should be added to
sys.path
; all other data types are ignored during import.— sys — System-specific parameters and functions — Python 3.10.5 documentation
sys.path
是 Python 搜索 module 的基准目录(即绝对导入)。其由环境变量 PYTHONPATH
和一些默认路径(和安装环境有关,参见 PYTHONHOME)组成,而在运行 script 时,script 的所在目录会被临时加入 sys.path[0]
中。如果运行的并不是 script(例如是交互式运行或从 stdin 中读取脚本代码),sys.path[0]
则被设置为空字符串,代表当前工作目录。
sys.path
有优先级,排在前面的优先级高。
需要特别注意的是,script 的所在目录不是当前工作目录。例如,在 D:\test
下执行
python path/to/file.py
时,sys.path[0]
为 D:\test\path\to\file.py
,而当前工作目录则是 D:\test
(也即 os.getcwd()
)。
当前工作目录是 Python 寻找其他文件时的基准路径,而所有绝对导入操作都只与 sys.path
有关,两者是完全不同的。
python -m
的情况稍有不同,参见后文。
python -m
Search
sys.path
for the named module and execute its contents as the__main__
module.Since the argument is a module name, you must not give a file extension (
.py
). The module name should be a valid absolute Python module name, but the implementation may not always enforce this (e.g. it may allow you to use a name that includes a hyphen).Package names (including namespace packages) are also permitted. When a package name is supplied instead of a normal module, the interpreter will execute
<pkg>.__main__
as the main module. This behaviour is deliberately similar to the handling of directories and zipfiles that are passed to the interpreter as the script argument.Note
This option cannot be used with built-in modules and extension modules written in C, since they do not have Python module files. However, it can still be used for precompiled modules, even if the original source file is not available.
If this option is given, the first element of
sys.argv
will be the full path to the module file (while the module file is being located, the
first element will be set to"-m"
). As with the-c
option, the current directory will be added to the start ofsys.path
.
-I
option can be used to run the script in isolated mode wheresys.path
contains neither the current directory nor the user’s site-packages directory. AllPYTHON*
environment variables are ignored, too.Many standard library modules contain code that is invoked on their execution as a script. An example is the
timeit
module:python -m timeit -s 'setup here' 'benchmarked code here'
python -m timeit -h # for details
Raises an auditing event
cpython.run_module
with argumentmodule-name
.See also
Equivalent functionality directly available to Python code
PEP 338 – Executing modules as scripts
Changed in version 3.1: Supply the package name to run a
__main__
submodule.Changed in version 3.4: namespace packages are also supported
— 1. Command line and environment — Python 3.10.5 documentation
在 sys.path
指定的目录中寻找 module 并以 __main__
module 的身份执行指定 module。
注意不要在名字后面加 .py
,因为我们已经把执行的文件当作 module 来看待。
如果指定的是一个 Package name(即目录名),将会执行 <pkg>.__main__
(即 <pkg>/__main__.py
)。
另外,如果使用 python -m a.b.module
,sys.argv
的首位将被设置为被执行 module 文件的完整路径(与之相对,python a/b/module.py
中 sys.argv[0]
将会是相对当前工作目录的路径,即 a/b/module.py
);同时,当前工作目录会被加入 sys.path
的首位。
python -m A.B.module
将顺次执行 A
、A.B
的 __init__.py
,即使该 module 没有任何导入行为。
python -m
对于直接执行 package 内部的代码是必要的。若直接以 script 方式运行,一旦涉及到任何高于该 script 所在目录(含该目录)的相对导入,Python 就会抛出如下错误:
ImportError: attempted relative import with no known parent package
而一个 module 也不能导入超过 python -m
参数指定的最顶层结构的 module,否则会抛出错误:
ImportError: attempted relative import beyond top-level package
sys.modules
The first place checked during import search is
sys.modules
. This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths. So iffoo.bar.baz
was previously imported,sys.modules
will contain entries forfoo
,foo.bar
, andfoo.bar.baz
. Each key will have as its value the corresponding module object.During import, the module name is looked up in
sys.modules
and if present, the associated value is the module satisfying the import, and the process completes. However, if the value isNone
, then aModuleNotFoundError
is raised. If the module name is missing, Python will continue searching for the module.
sys.modules
is writable. Deleting a key may not destroy the associated module (as other modules may hold references to it),
but it will invalidate the cache entry for the named module, causing Python to search anew for the named module upon its next
import. The key can also be assigned toNone
, forcing the next import of the module to result in aModuleNotFoundError
.Beware though, as if you keep a reference to the module object, invalidate its cache entry in
sys.modules
, and then re-import the named module, the two module objects will not be the same. By contrast,importlib.reload()
will reuse the same module object, and simply reinitialise the module contents by rerunning the module’s code.
sys.modules
是一个 dict
,Python 在导入之前会去检查 sys.module
里是否已经存有需要的 module 的 module object。如果有,就直接用这个;如果值为 None
(意思是以前找过但没找到),就直接报错;如果该键值对不存在,就继续搜索过程。总之,sys.modules
扮演了一个类似 cache 的角色。
对于形如 A.B.C
的导入,Python 会顺次导入 A
、A.B
和 A.B.C
并把他们加入 sys.modules
。
参考
关于 Python 的 import的更多相关文章
- python中import和from...import区别
在python用import或者from...import来导入相应的模块.模块其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模块导入到我们的程序中 ...
- Python中import的使用
python中的import语句是用来导入模块的,在python模块库中有着大量的模块可供使用,要想使用这些文件需要用import语句把指定模块导入到当前程序中. import语句的作用 import ...
- python 的import机制2
http://blog.csdn.net/sirodeng/article/details/17095591 python 的import机制,以备忘: python中,每个py文件被称之为模块, ...
- python之import机制
1. 标准 import Python 中所有加载到内存的模块都放在 sys.modules .当 import 一个模块时首先会在这个列表中查找是否已经加载了此模块,如果加载了则只是将 ...
- python中import和from...import...的区别
python中import和from...import...的区别: 只用import时,如import xx,引入的xx是模块名,而不是模块内具体的类.函数.变量等成员,使用该模块的成员时需写成xx ...
- python的import与from...import的不同之处
在python用import或者from...import来导入相应的模块.模块其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模块导入到我们的程序中 ...
- (原)python中import caffe提示no module named google.protobuf.internal
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5993405.html 之前在一台台式机上在python中使用import caffe时,没有出错.但是 ...
- linux环境下 python环境import找不到自定义的模块
linux环境下 python环境import找不到自定义的模块 问题现象: Linux环境中自定义的模块swport,import swport 出错.swport模块在/root/sw/目录下. ...
- 关于Python的import机制原理
很多人用过python,不假思索地在脚本前面加上import module_name,但是关于import的原理和机制,恐怕没有多少人真正的理解.本文整理了Python的import机制,一方面自己总 ...
- [转] Python的import初探
转载自:http://www.lingcc.com/2011/12/15/11902/#sec-1 日常使用python编程时,为了用某个代码模块,通常需要在代码中先import相应的module.那 ...
随机推荐
- XCTF练习题---MISC---stegano
XCTF练习题---MISC---stegano flag:flag{1nv151bl3m3554g3} 解题步骤: 1.观察题目,下载附件 2.打开发现是一张PDF图片,尝试转换word无果后,想到 ...
- 为什么 IPv6 难以取代 IPv4
网络层协议承担了分组(Packet)转发和路由选择两大功能,它能够为上层提供在不同主机之间运输分组的职责,IP 协议作为网络层协议,它虽然只能提供无连接的.不可靠的服务,但是它在今天的互联网中起到了极 ...
- 『现学现忘』Git基础 — 21、git diff命令
目录 1.git diff 命令说明 2.比较工作区与暂存区中文件的差别 3.比较暂存区与本地库中文件的差别 4.总结git diff命令常见用法 5.总结 1.git diff 命令说明 在comm ...
- 【远古黑历史】List链表及其功能
前言 我知道有学校是禁用STL的, 但STL是真的香,加个蛋,嗯,好吃 所以,本人希望有更多OIer能使用STL,减少工作量! 初见STL 首先,什么是STL? STL,全称 Standard Tem ...
- p2p-tunnel 打洞内网穿透系列(三)TCP转发访问内网web服务
系列文章 p2p-tunnel 打洞内网穿透系列(一)客户端配置及打洞 p2p-tunnel 打洞内网穿透系列(二)TCP转发访问远程共享文件夹 p2p-tunnel 打洞内网穿透系列(三)TCP转发 ...
- Oracle19c单实例数据库配置OGG单用户数据同步测试
目录 19c单实例配置GoldenGate 并进行用户数据同步测试 一.数据库操作 1.开启数据库附加日志 2.开启数据库归档模式 3.开启goldengate同步 4.创建goldengate管理用 ...
- 用 Python 远程控制 Windows 服务器,太好用了!
在很多企业会使用闲置的 Windows 机器作为临时服务器,有时候我们想远程调用里面的程序或查看日志文件 Windows 内置的服务「 winrm 」可以满足我们的需求 它是一种基于标准简单对象访问协 ...
- URL 是什么?
URL 是什么? 本文写于 2020 年 5 月 16 日 URL 是什么?天天听到人家说到这个名词,那它到底是什么? URL 是统一资源定位符,Uniform Resource Locator. 俗 ...
- JSON数据传输大法第一式——用OADate处理日期格式
JSON作为一种轻量级的数据交换格式,通常采用完全独立于编程语言的文本格式来存储和表示数据.它的层次结构简洁清晰,易于人们的阅读和编写,此外机器编写和生成也会变得容易,可以有效地提升网络传输效率,这些 ...
- 无线:WEP
WEP是Wired Equivalent Privacy的简称,有线等效保密(WEP)协议是对在两台设备间无线传输的数据进行加密的方式,用以防止非法用户窃听或侵入无线网络.不过密码分析学家已经找出 W ...