Python的模块引入
环境:
大部分在Python3.7下测试执行
import语句很长时该怎么书写
可以:
1 |
|
也可以:
1 |
|
但官方建议使用括号:
1 |
|
模块查找顺序
- 先搜索内置模块(
built-in module
,内置在python编译器),如winreg
模块(或叫_winreg
模块,只在Windows下存在) - 从
sys.path
(list类型)指定的一个个目录里搜索。
关于sys.path
执行python script.py
时,sys.path
的第一个元素是script.py
文件所在的目录;如果不指定脚本文件,如;直接执行python
进入交互模式,或执行python -m expectd.package.module
等,sys.path
的第一个元素就是空字符串,代表执行python
命令时所在的目录。
sys.path
还包括PYTHONPATH
环境变量指定的目录,和安装时指定的默认值(The installation-dependent default
)
绝对引入
一个目录结构为:
1 |
|
在test.py
里写import string
,然后在package/
目录的上一层目录(以让python找到我们自己写的package
的位置)执行python -m package.test
,那import
的是同目录下的string
模块,还是python自带的string
模块呢?
在Python2.7下测试,是引入同目录下的string
模块,因为import string
语句会先查找同目录下的模块。这样的引入方式,无法在不重命名package/string.py
文件的情况下导入python自带的string
模块。所以Python加了一个绝对引入(absolute import
),且在python3中默认使用,而在Python 2中使用绝对引入,需要在文件头写:from __future__ import absolute_import
。
绝对引入是指import
时,都是从sys.path
指定的目录下查找包或模块。如:import foo
,from foo import bar
。有了绝对引入,那要引入同目录下的模块,需要加上.
符号,这叫相对引入(relative import
, 相对于当前模块来引入)。如:from .foo import bar
。而要引入上一层的模块,就用两个点,要引入上上一层就用三个点,如:from ..foo import bar
引入上一层的模块。另外,要引入上一层的模块时,不可以写成import ..foo
,而是写成from .. import foo
。
所以上面在python3测试,是引入python自带的string
模块,若要引入同目录下的string模块,就写成from . import string
__init__.py
文件
在目录下有__init__.py
文件,Python才会把该目录看作包(package
),在该文件中可以写初始化代码(引入包或包里模块等时会执行__init__.py
),也可以设置__all__
变量。
一个包的目录结构为:
1 |
|
如果__init__.py
文件的__all__
变量没设置,执行from package import *
或import package
并不会引入package
下的子模块或子包,而仅仅是引入该包(一般会执行__init__.py
的代码)。需要这样写from package import moduleX, moduleY
,就可以引入模块。
如果__init__.py
文件里写__all__ = ['moduleX', 'moduleY']
,执行from package import *
就会引入__all__
里的模块或子包,也就是会在当前域中存在moduleX
和moduleY
变量。
python script
有些时候并不是要写一个模块供调用,而是写几个脚本来执行。
目录结构为:
1 |
|
(因为要在test.py
文件中引入sub/fibo.py
,需要告诉Python sub
目录是个包,所以要放置__init__.py
文件)
在test.py
里引入
1 |
|
然后在my_scripts/
目录下执行python test.py
。可以引入,没有报错。这是为什么?
像上面说的,sys.path
的第一个元素是test.py
所在的目录,所以上面两个绝对引入是可以找得到helper
跟fibo
的。
python -m命令
模块除了被import
,也可以直接用python -m
命令把模块当脚本来执行。如:python -m json.tool
执行json包里的tool模块,用来格式化JSON数据。还有python -m pdb script.py
、python -m profile script.py
等。
python -m
命令,实际上是调用runpy
模块的runpy.run_module(mod_name, init_globals=None, run_name=None, alter_sys=False)
方法,其会搜索模块,依据加载的包、模块名来设置__package__
属性等,以便让相对引入正确执行。例如执行python -m json.tool
时,__name__
设置成json.tool
,__package__
设置成"json.tool".rpartition('.')[0]
,即json
。
参考链接
- Python Modules: https://docs.python.org/2.7/tutorial/modules.html
- PEP 328 – Imports: Multi-Line and Absolute/Relative:https://www.python.org/dev/peps/pep-0328/
- PEP 366 – Main module explicit relative imports: https://www.python.org/dev/peps/pep-0366/
- PEP 338 – Executing modules as scripts: https://www.python.org/dev/peps/pep-0338/
其它
1 |
|
fibo
是个模块,该import
会导入fibo
模块下所有变量,除了以_
开头的变量。
dir()
不会列出内置函数和内置变量,如果想要获取内置函数和内置变量,使用import builtins; dir(builtins)
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!