Python 3 学习笔记

人生苦短,我用 Python。

👉文章列表
Python 3 学习笔记 ⏬ 数字 数字的进制转换 集合 set 路径处理 sys.path 模块 使用 SimpleHttpServer 快速构建静态文件服务 包管理器 pip 的使用 virtualenv 的使用 CRC32 BeautifulSoup 使用指南 使用 BeautifulSoup 去除 HTML 中的注释 PyMySQL 使用指南 json 处理 yaml 处理 使用 getopt 库解析命令行参数 使用 argparse 库解析命令行参数 Jinja2 模板引擎

Python 3: 模块


【编写中】

1、模块是什么?

模块一种组织代码的形式。当代码规模变大后,需要将代码拆分到多个 Python 源代码文件中。对于一个程序,运行的入口一般只有一个,那么,除了程序入口之外的所有源文件,都是模块。

2、非package下的源文件导入模块的顺序

顺序是:

  1. 被执行源文件所在目录下的模块
  2. PYTHONPATH 环境变量指定的目录
  3. Python 自带的标准模块
  4. 安装在 site-packages 下的第三方模块
  5. .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'

( 本文完 )

文章目录