【编写中】
1、模块是什么?
模块一种组织代码的形式。当代码规模变大后,需要将代码拆分到多个 Python 源代码文件中。对于一个程序,运行的入口一般只有一个,那么,除了程序入口之外的所有源文件,都是模块。
2、非package下的源文件导入模块的顺序
顺序是:
- 被执行源文件所在目录下的模块
- PYTHONPATH 环境变量指定的目录
- Python 自带的标准模块
- 安装在 site-packages 下的第三方模块
.pth
后缀文件中配置的目录
这些最终会在 sys.path 中体现出来。
示例2.1
在 py-project 目录下创建文件 main.py:
py-project
└── main.py
import sys
for path in sys.path:
print(path)
运行:
$ python3 main.py
/Users/letian/Desktop/py-project
/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python36.zip
/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6
/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload
/Users/letian/Library/Python/3.6/lib/python/site-packages
/usr/local/lib/python3.6/site-packages
$ cd ..
$ python3 py-project/main.py
/Users/letian/Desktop/py-project
/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python36.zip
/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6
/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload
/Users/letian/Library/Python/3.6/lib/python/site-packages
/usr/local/lib/python3.6/site-packages
示例2.2
项目结构:
py-project
├── main.py
└── module.py
module.py
内容如下:
def get_name():
return "python"
main.py
内容如下:
import module
print(module.get_name())
运行:
$ python3 main.py
python
$ cd ..
$ python3 py-project/main.py
python
示例2.3
项目结构:
py-project
└── main.py
main.py 内容如下:
import string // python 自带模块
print(string)
运行:
$ python3 main.py
<module 'string' from '/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py'>
如果 py-project
目录中也有一个 string 模块呢? 添加 string.py,项目结构变成:
py-project
├── main.py
└── string.py
执行 main.py:
$ python3 main.py
<module 'string' from '/Users/letian/Desktop/py-project/string.py'>
可以看到,优先使用了自定义的 string 模块。
3、package下的源文件导入顺序
当一个目录中存在 __init__.py
文件时,那么这个目录就是一个 package。如果子目录也有 __init__.py
文件,那么子目录就是一个子 package。
示例3.1
项目结构:
py-project
└── dev
├── __init__.py
├── main.py
└── string.py
main.py 内容如下:
import string
print(string)
运行:
$ cd dev
$ python3 main.py
<module 'string' from '/Users/letian/Desktop/py-project/dev/string.py'>
$ cd ..
$ python3 dev/main.py
<module 'string' from '/Users/letian/Desktop/py-project/dev/string.py'>
但是,如果以模块的形式运行,结果会有不同:
$ python3 -m dev.main
<module 'string' from '/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/string.py'>
也就是,以模块的形式运行时,优先使用Python内置模块。
4、不能直接执行的场景
示例4.1
项目结构:
py-project
└── dev
├── __init__.py
├── main.py
└── string.py
main.py 内容如下:
from dev import string
print(string)
以下方式会失败:
$ python3 dev/main.py
Traceback (most recent call last):
File "dev/main.py", line 1, in <module>
from dev import string
ModuleNotFoundError: No module named 'dev'
$ cd dev
$ python3 main.py
Traceback (most recent call last):
File "main.py", line 1, in <module>
from dev import string
ModuleNotFoundError: No module named 'dev'
以下方式会成功:
$ PYTHONPATH="." python3 dev/main.py
<module 'dev.string' from '/Users/letian/Desktop/py-project/dev/string.py'>
$ python3 -m dev.main
<module 'dev.string' from '/Users/letian/Desktop/py-project/dev/string.py'>
示例4.2
项目结构:
py-project
└── dev
├── __init__.py
├── main.py
└── string.py
main.py 内容如下:
from . import string
print(string)
以下方式会失败:
$ python3 dev/main.py
Traceback (most recent call last):
File "dev/main.py", line 1, in <module>
from . import string
ImportError: cannot import name 'string'
$ PYTHONPATH="." python3 dev/main.py
Traceback (most recent call last):
File "dev/main.py", line 1, in <module>
from . import string
ImportError: cannot import name 'string'
$ cd dev
$ python3 main.py
Traceback (most recent call last):
File "main.py", line 1, in <module>
from . import string
ImportError: cannot import name 'string'
以下方式会成功:
$ python3 -m dev.main
<module 'dev.string' from '/Users/letian/Desktop/py-project/dev/string.py'>
5、其他示例
我们在~/Desktop
创建py-project
目录,并在其中添加一些 Python 代码:
py-project
├── dev
│ ├── __init__.py
│ ├── util.py
│ ├── main2.py
│ ├── main3.py
│ └── main4.py
└── main1.py
dev 目录中含有__init__.py
,所以dev
是一个module。
dev/util.py 内容:
def get_name():
return "乐天的开发教程"
dev/main2.py 内容:
from .util import get_name
print(get_name())
dev/main3.py 内容:
from dev.util import get_name
print(get_name())
dev/main4.py 内容:
from util import get_name
print(get_name())
main1.py 内容:
from dev.util import get_name
print(get_name())
在 py-project 目录执行:
$ cd py-project
$ python3 main1.py
乐天的开发教程
$ python3 dev/main2.py
Traceback (most recent call last):
File "dev/main2.py", line 1, in <module>
from .util import get_name
ModuleNotFoundError: No module named '__main__.util'; '__main__' is not a package
$ python3 dev/main3.py
Traceback (most recent call last):
File "dev/main3.py", line 1, in <module>
from dev.util import get_name
ModuleNotFoundError: No module named 'dev'
$ python3 dev/main4.py
乐天的开发教程
$ python3 -m dev.main2
乐天的开发教程
$ python3 -m dev.main3
乐天的开发教程
在 py-project/dev 目录执行:
$ cd py-project/dev
$ python3 main2.py
Traceback (most recent call last):
File "main2.py", line 1, in <module>
from .util import get_name
ModuleNotFoundError: No module named '__main__.util'; '__main__' is not a package
$ python3 main3.py
Traceback (most recent call last):
File "main3.py", line 1, in <module>
from dev.util import get_name
ModuleNotFoundError: No module named 'dev'
$ python3 main4.py
乐天的开发教程
$ python3 ../main1.py
乐天的开发教程
$ python3 -m main2
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/letian/Desktop/py-project/dev/main2.py", line 1, in <module>
from .util import get_name
ImportError: attempted relative import with no known parent package
$ python3 -m main3
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/letian/Desktop/py-project/dev/main3.py", line 1, in <module>
from dev.util import get_name
ModuleNotFoundError: No module named 'dev'