doc: 阅读python module文档

This commit is contained in:
asahi
2025-08-16 22:09:44 +08:00
parent 7d7d8746e6
commit 68c21c80d1

View File

@@ -82,6 +82,13 @@
- [from ... import ...](#from--import--1)
- [as](#as)
- [execute module as script](#execute-module-as-script)
- [module search path](#module-search-path-1)
- [`sys.path`初始化](#syspath初始化)
- [standard module](#standard-module)
- [dir function](#dir-function)
- [packages](#packages)
- [import \* from package](#import--from-package)
- [包内部相互引用](#包内部相互引用)
# Python
@@ -1155,3 +1162,193 @@ if __name__ == "__main__":
并且在module被导入时`sys`并不会被导入。
### module search path
当module名为`spam`的module被导入时interpreter会按照如下顺序来进行查找
1. 首先interpreter会从built-in module中查找`spam`
2. 如果步骤1没有查询到其会在`sys.path`变量定义的路径中查找名为`spam.py`的文件
#### `sys.path`初始化
在python启动时其会初始化module search path初始化后的module search path可以通过`sys.path`来进行访问。
在`sys.path`中,组成如下:
- `sys.path`中第一条entry是包含input script的目录如果存在input script
- 若未指定input script如`运行交互式shell`、`运行-c command`、`运行-m module`时,`sys.path`的第一条entry则是当前目录
- `PYTHONPATH`环境变量中定义的路径也会被添加到search path中
- 包含`standard python modules及其依赖的拓展modules`的路径也会别添加到module search path中
- 拓展modules在windows平台中后缀名为`.pyd`,在其他平台中后缀名为`.so`
- 其中,`standard python modules`是平台无关的,被称为`prefix`
- `extension modules`则是平台相关的,被称为`exec_prefix`
> python支持通过`-c`来直接运行python命令示例如下
> ```shell
> python -c 'print(1+22*33)'
> ```
>
> python还支持通过`-m`来直接运行module示例如下
> ```bash
> echo '{"name":"John","age":30}' | python -m json.tool
> ```
> 部分系统支持symlinks故而包含input script的目录路径会在input script的symlink被follow之后才进行计算。故而`包含symlink`的目录并不会被添加到sys.path中
在`sys.path`被初始化之后python程序可以对`sys.path`进行修改。
在`sys.path`中,包含被运行文件的目录路径被放在了`sys.path`中最开始的位置,代表如果运行文件路径中如果存在和`standard library module`相同名称的文件,那么运行文件路径下的同名文件将会覆盖`standard library module`。
### standard module
python附带了一个包含standard modules的library。`standard modules`中部分modules是内置在interpreter中的built modules中的内容可能并不是语言核心操作的一部分但是能够提供对操作系统的访问例如系统调用等。
built-in modules中的module在不同平台是可选的例如`winreg` module只存在于windows平台。但是`sys`module在所有平台的python interpreter中都包含。
### dir function
内置的`dir()`方法会查看在module中定义了哪些名称其返回了一个sorted string list
```bash
>>>import fibo, sys
>>>dir(fibo)
['__name__', 'fib', 'fib2']
>>>dir(sys)
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
'__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
'__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
'_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
'warnoptions']
```
当没有为`dir()`方法传递参数时,`dir()`方法会列出当前已经定义的名称:
```python
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
```
其列出的名称中包含所有类型变量、module、function等
`dir`方法并不会列出内置的方法和变量,如果想要查看那些,可以使用`dir(builtins)`
```bash
import builtins
dir(builtins)
```
### packages
packge是一种结构化python modules命名空间的方法其使用了`dotted module names`。例如module name为`A.B`其代表的是位于package A下的submodule B。
就像module可以使module的开发者们不用担心使用了和其他module中一样的变量/函数名一样dotted module name可以令module的开发者不用担心使用了和其他module相同的module name。
如果你要定义一系列的modules统一处理不同格式的sound files和sound data可以采用如下的package结构
```
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
```
当对package进行导入时python会从`sys.path`中查询package的子目录。
其中,`__init__.py`文件用于`让python将该目录看作是package`。`__init__.py`文件可以是空文件,但是`也可以包含对package进行初始化的代码`或`设置__all__变量`。
在使用package中可以单独导入package中的module
```py
import sound.effects.echo
```
上述示例中导入了`sound.effects.echo`module在对module进行使用时必须采用如下方式指定mdoule的fullname
```py
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
```
另一种可选的导入方式如下:
```py
from sound.effects import echo
```
在使用module时只需要指定echo即可
```py
echo.echofilter(input, output, delay=0.7, atten=4)
```
同时也可以直接导入module中的方法
```py
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)
```
在使用`import item.subitem.subsubitem`这类语法时除了最后的item外其余item必须都要是package最后的item可以是package或module但不能是module中的内容。
#### import * from package
在对package执行`import *`的语法时,其导入行为准许如下规范:
- 如果package的`__init__.py`文件中定义了`__all__`变量,其将认为`__all__`中定义了所有应该被`import *`所导入的module name
故而package的开发者应当负责在package版本迭代时将`__all__`进行更新;当然,开发者页可以决定不对`import *`进行支持,不定义`__all__`。
示例如下,`sound/effects/__init__.py`中可能包含如下内容:
```py
__all__ = ["echo", "surround", "reverse"]
```
其代表`from sound.effect import *`将会导入`echo, surround, reverse`三个module。
注意本地定义的名称可能会遮挡submodules。例如如果在`sound/effects/__init__.py`中定义了一个reverse函数那么`from sound.effects import *`将只会导入`echo, surround`两个module。
```py
__all__ = [
"echo", # refers to the 'echo.py' file
"surround", # refers to the 'surround.py' file
"reverse", # !!! refers to the 'reverse' function now !!!
]
def reverse(msg: str): # <-- this name shadows the 'reverse.py' submodule
return msg[::-1] # in the case of a 'from sound.effects import *'
```
如果在`__init__.py`中没有定义`__all__`,那么`from sound.effects import *`只会导入`__init__.py`中的其他定义内容,示例如下:
```py
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
```
### 包内部相互引用
在同一个包中不同subpackage中的module可以对彼此进行引用。引用支持绝对路径和相对路径例如`sound.filters.vocoder`在对`sound.effects`中定义的包进行import时可以采用如下方式
- 绝对路径:`from sound.effects import echo`
- 相对路径:`from ..effects import echo`
在使用相对路径的导入时,示例如下:
当从`surround`执行相对路径导入时,可以执行如下形式的导入
```py
from . import echo # 位于相同的subpackage中
from .. import formats # 访问../formats
from ..filters import equalizer # 访问../filters中的equalizer
```