Contents

Python教程-模块

本系列为作者在官网学习python时做的笔记,详见python官网

python标准库官方文档,查阅标准库相关的内容

python语言参考,查看python语法,该文档是简洁的,但试图做到准确和完整。非必要的内建对象类型和内建函数、模块的语义描述在 Python 标准库 中。

标准库和语言参考涵盖了python的所有内容,他们是互补的,如果在语言参考中没有找到需要的内容那么就一定在便准库文档中。

更多有关模块的信息

模块可以包含可执行的语句以及函数定义。这些语句用于初始化模块。它们仅在模块 第一次 在 import 语句中被导入时才执行。(当文件被当作脚本运行时(模块的__name__属性为main),它们也会执行。)

每个模块都有它自己的私有符号表,不必担心模块内全局变量与用户的全局变量发生意外冲突。另一方面,可以用跟访问模块内的函数的同样标记方法,去访问一个模块的全局变量,modname.itemname。

可以把其他模块导入模块。被导入的模块名存在导入方模块的全局符号表里。

可以把名字从一个被调模块内直接导入到现模块的符号表里。例如:

1
2
from fibo import fib, fib2
fib(500)

这并不会把被调模块名引入到局部变量表里(因此在这个例子里,fibo 是未被定义的)。

还可以导入模块内定义的所有名称:

1
2
3
>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

这会调入所有非以下划线(_)开头的名称。不推荐使用,有覆盖你本地变量的风险。在交互式编译器中为了节省打字可以这么用。

如果模块名称之后带有 as,则跟在 as 之后的名称将直接绑定到所导入的模块(原来的模块名不会被导入)。

1
2
3
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

这种方式也可以在用到 from 的时候使用:

1
2
3
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

每个模块在每个解释器会话中只被导入一次。如果你更改了你的模块,则必须重新启动解释器。如果它只是一个要交互式地测试的模块,可以使用 importlib.reload()

1
2
import importlib
importlib.reload(modulename)

以脚本的方式执行模块

当你用下面方式运行一个Python模块:

1
python fibo.py <arguments>

这项操作将执行模块里的代码,而且会把 __name__ 赋值为 "__main__"。 也就是会运行下面的代码:

1
2
3
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

如果模块是被导入的,那些代码是不运行的:

1
2
>>> import fibo
>>>

模块搜索路径

当一个名为 spam 的模块被导入的时候,解释器首先寻找具有该名称的内置模块。如果没有找到,然后解释器从 sys.path 变量给出的目录列表里寻找名为 spam.py 的文件。sys.path 初始有这些目录地址:

  • 包含输入脚本的目录(或者未指定文件时的当前目录)。
  • PYTHONPATH (一个包含目录名称的列表,它和shell变量 PATH 有一样的语法)。
  • 取决于安装的默认设置

在初始化后,Python程序可以更改 sys.path。除非有意更换,否则这是错误。

“编译过的”Python文件

为了加速模块载入,Python在 ${PYTHON_HOME}/Lib/__pycache__ 目录里缓存了每个模块的编译后版本,名称为 module.version.pyc ,其中名称中的版本字段对编译文件的格式进行编码; 它一般使用Python版本号。如telnetlib.cpython-38.pyc

Python根据编译版本检查源的修改日期,以查看它是否已过期并需要重新编译。这是一个完全自动化的过程。

编译的模块与平台无关,因此可以在具有不同体系结构的系统之间共享相同的库。

Python在两种情况下不会检查缓存而是直接编译:

  • 从命令行直接载入的模块
  • 没有源模块

给专业人士的一些小建议:

  • 你可以在Python命令中使用 -O 或者 -OO 开关, 以减小编译后模块的大小。 -O 开关去除断言语句,-OO 开关同时去除断言语句和 doc 字符串。
  • 一个从 .pyc 文件读出的程序并不会比它从 .py 读出时运行的更快,.pyc 文件唯一快的地方在于载入速度。
  • compileall 模块可以为一个目录下的所有模块创建.pyc文件。

标准模块

一些模块内置于解释器中;它们提供对不属于语言核心但仍然内置的操作的访问,以提高效率或提供对系统调用等操作系统原语的访问。这些模块的集合是一个配置选项,它也取决于底层平台。例如,winreg 模块只在Windows操作系统上提供。一个特别值得注意的模块 sys,它被内嵌到每一个Python解释器中。变量 sys.ps1 和 sys.ps2 定义用作主要和辅助提示的字符串:

1
2
3
4
5
6
7
8
9
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

这两个变量只有在编译器是交互模式下才被定义。

sys.path 变量是一个字符串列表,用于确定解释器的模块搜索路径。该变量被初始化为从环境变量 PYTHONPATH 获取的默认路径,或者如果 PYTHONPATH 未设置,则从内置默认路径初始化。可以使用标准列表操作对其进行修改:

1
2
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')

dir() 函数

内置函数 dir() 用于查找模块定义的名称。 它返回一个排序过的字符串列表:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)  
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
 '__package__', '__stderr__', '__stdin__', '__stdout__',
 '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
 '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
 'base_exec_prefix', 'base_prefix', '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',
 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
 'thread_info', 'version', 'version_info', 'warnoptions']

如果没有参数,dir() 会列出你当前定义的名称:

1
2
3
4
5
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

注意:它列出所有类型的名称:变量,模块,函数,等等。

dir() 不会列出内置函数和变量的名称。如果你想要这些,它们的定义是在标准模块 builtins 中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
>>> import builtins
>>> 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', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError',
 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
 '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
 'all', 'any', 'ascii', 'bin', 'bool', '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']

包是目录,模块是py文件

包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法。

必须要有 __init__.py 文件才能让 Python 将包含该文件的目录当作包。 在最简单的情况下,__init__.py 可以只是一个空文件,但它也可以执行包的初始化代码或设置 __all__ 变量,

包的用户可以从包中导入单个模块,例如:

1
import sound.effects.echo

这会加载子模块 sound.effects.echo ,但引用它时必须使用它的全名。

1
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

导入子模块的另一种方法是

1
from sound.effects import echo

这也会加载子模块 echo ,并使其在没有包前缀的情况下可用:

1
echo.echofilter(input, output, delay=0.7, atten=4)

另一种形式是直接导入所需的函数或变量:

1
from sound.effects.echo import echofilter

同样,这也会加载子模块 echo,但函数 echofilter() 直接可用:

1
echofilter(input, output, delay=0.7, atten=4)

请注意,当使用 from package import item 时,item可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数,类或变量。 import 语句首先测试是否在包中定义了item;如果没有,它假定它是一个模块并尝试加载它。如果找不到它,则引发 ImportError 异常。

相反,当使用 import item.subitem.subsubitem 最后一项不能是前一项中定义的类或函数或变量。

从包中导入 *

from sound.effects import * 找到包中存在哪些子模块,并将它们全部导入。这可能需要很长时间。

如果一个包的 __init__.py 代码定义的名为 __all__ 的列表会被视为在遇到 from package import * 时应该导入的模块名列表。例如,文件 sound/effects/__init__.py 可以包含以下代码:

1
__all__ = ["echo", "surround", "reverse"]

这意味着 from sound.effects import * 将导入 sound 包的三个命名子模块。

如果没有定义 __all__from sound.effects import * 语句 不会 从包 sound.effects 中导入所有子模块到当前命名空间;它只确保导入了包 sound.effects 任何在__init__.py中的初始化代码定义的任何名称。 这包括 __init__.py 定义的任何名称(以及显式加载的子模块):

子包参考

当包被构造成子包时(与示例中的 sound 包一样),你可以使用绝对导入(相对项目目录而言)来引用兄弟包的子模块。例如,如果模块 sound.filters.vocoder 需要在 sound.effects 包中使用 echo 模块,它可以使用 from sound.effects import echo 。

你还可以使用import语句的 from module import name 形式编写相对导入。这些导入使用前导点来指示相对导入中涉及的当前包和父包。例如,从 surround 模块,你可以使用:

1
2
3
from . import echo
from .. import formats
from ..filters import equalizer

推荐使用绝对导入

多个目录中的包

包支持另一个特殊属性, __path__ 。它被初始化为一个列表,其中包含在执行该文件中的代码之前保存包的文件 __init__.py 的目录的名称。这个变量可以修改;这样做会影响将来对包中包含的模块和子包的搜索。

虽然通常不需要此功能,但它可用于扩展程序包中的模块集。

还是很重要的,在服务器上很好使用

腾讯云开发者社区 静谧星空TEL python引入相同和不同(模块)文件夹下py文件的类

1
2
3
4
## 将上级目录加入python系统路径,引入模块x,x在包y,这里的路径是y所在的目录
sys.path.append(r'..')
## from 包名.文件名 import 类名
from MongoDB.MongoDBUtil import MongoDBUtil

多次import一个模块

多次import一个模块只会执行一次

 |