模块和包¶
参考:
每个.py
文件都是一个模块,包则是多个模块的组合
模块加载¶
使用import语句加载并初始化模块,也可以使用from ... import ...
语句仅加载模块中的某个变量、函数、类、子模块
import a
import a.b.c
import a.b.c as c
from a.b import c
使用as
关键字后,其模块名重定义为c
模块重载¶
使用库importlib
的reload
方法
def reload(module):
直接输入模块名即可
模块信息¶
获取模块名¶
可以在模块内部通过全局变量__name__
获取
# 定义fibo.py
def print_module_name():
print(__name__)
# 定义main.py
import module.fibo as fibo
if __name__ == '__main__':
print(__name__)
fibo.print_module_name()
输出如下:
__main__
module.fibo
当前调用模块(主模块)的模块名变成__main__
全局符号表/本地符号表¶
每个模块都有自己私有的全局符号表以及本地符号表,使用函数globals()和locals()获取
import module.fibo as fibo
a = 3
def func():
c = 5
print(locals())
if __name__ == '__main__':
b = 4
print(globals())
func()
全局/本地符号表都是一个字典
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fc805108f60>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/zj/pythonProjects/first/module/main.py', '__cached__': None, 'fibo': <module 'module.fibo' from '/home/zj/pythonProjects/first/module/fibo.py'>, 'a': 3, 'func': <function func at 0x7fc8051421e0>, 'b': 4}
{'c': 5}
注意 1:全局符号表包括全局变量、函数、模块信息
注意 2:本地符号表包括函数局部变量、方法等信息
如果在全局路径下调用方法locals
,其作用和globals
一样
模块搜索路径¶
加载import module
时,解释器首先寻找内置模块是否匹配,然后按sys.path
给出的目录列表进行搜索
import sys
print(sys.path)
在模块sys
的属性path
中按顺序保存有
- 包含输入脚本的目录(或未指定文件时的当前目录)
- 全局变量PYTHONPATH
python
安装的默认设置
['/home/zj/pythonProjects/first/module',
'/home/zj/pythonProjects/first',
'/home/zj/software/anaconda/anaconda3/lib/python37.zip',
'/home/zj/software/anaconda/anaconda3/lib/python3.7',
'/home/zj/software/anaconda/anaconda3/lib/python3.7/lib-dynload',
'/home/zj/software/anaconda/anaconda3/lib/python3.7/site-packages',
'/home/zj/software/jetbrains/pycharm-2018.3.3/helpers/pycharm_matplotlib_backend']
同时还可以在运行过程中添加搜索路径
sys.path.append('../../adfa')
搜索名称列表¶
使用函数dir能够获取当前模块或指定模块的属性列表
def dir(p_object=None):
import module.fibo as fiboooo
import sys
a = 3
def func():
c = 5
print(locals())
if __name__ == '__main__':
print(dir())
print(dir(fiboooo))
如果没有输入参数,则返回当前模块的属性列表,包括定义的变量、函数、类、模块等信息
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'fiboooo', 'func', 'sys']
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fib', 'fib2', 'print_module_name']
标准模块属性¶
python
内置函数和属性可通过检索模块builtins
获取
import builtins
print(dir(builtins))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
包¶
当同一目录下有多个模块,甚至其子目录下还有模块,可以在每层目录下创建文件__init__.py
,解释器会将该层目录视为包,使用包能够更有效的管理模块
.
├── main.py
└── module
├── fibo.py
├── __init__.py
└── test.py
module
是一个包
加载包¶
可以使用import
语句加载包中的模块
import module.fibo as fibo
import module.test as test
if __name__ == '__main__':
fibo.fib(3)
test.test()
在__init__.py
上实现模块加载,在其他模块上使用
import module.test
import module.fibo
上面实现代码等价如下
from module import *
if __name__ == '__main__':
fibo.fib(3)
test.test()
加载部分模块¶
如果只想一次性加载部分的模块,在__init__.py
中使用变量__all__
__all__ = ['test']
如果执行加载语句from module import *
仅能载入模块test
from module import *
if __name__ == '__main__':
# fibo.fib(3)
test.test()
子模块导入¶
当子包下的模块要引用另一个子包模块时,推荐使用绝对路径进行导入
├── main.py
└── module
├── fibo.py
├── __init__.py
├── sub1
│ ├── __init__.py
│ └── sub1_test.py
├── sub2
│ ├── __init__.py
│ └── sub2_test.py
└── test.py
模块sub1_test
引入模块sub2_test
# sub1_test
import module.sub2.sub2_test as test
def operation():
test.operation()
if __name__ == '__main__':
operation()
# sub2_test
def operation():
print(__name__)
运行模块sub1_test.py
,输出如下:
module.sub2.sub2_test
在main.py
中引入sub1_test.py
,并执行opeation
方法
import module.sub1.sub1_test as test
if __name__ == '__main__':
test.operation()
输出如下:
module.sub2.sub2_test
__pychache__
¶
运行完成后,在每个模块的路径下生成文件夹__pychache__
,用于缓存模块编译版本,其命名格式为
module_name.python_version.pyc
缓存文件由python
解释器自动生成,根据修改日期决定是否重编译,其目的是加快载入速度
└── module
├── fibo.py
├── __init__.py
├── __pycache__
│ ├── fibo.cpython-37.pyc
│ ├── __init__.cpython-37.pyc
│ └── test.cpython-37.pyc
├── sub1
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-37.pyc
│ │ └── sub1_test.cpython-37.pyc
│ └── sub1_test.py
├── sub2
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-37.pyc
│ │ └── sub2_test.cpython-37.pyc
│ └── sub2_test.py
└── test.py
pycharm使用注意¶
在pycharm
使用时需要设置当前文件夹为Source Root
,否则无法载入当前目录下的其他.py
文件
比如,工程目录如下:
├── docs
...
...
├── LICENSE
├── README.md
├── requirements.txt
└── src
├── __init__.py
├── BB.py
├── AA.py
└── __pycache__
.py
文件在src
目录下,此时无法在AA.py
文件中载入BB.py
from BB import BBBTest
需要右键src -> Mark Directory as -> Mark as source root