Python文档学习笔记(8)--模块
创建一个名为fibo.py
的文件
# Fibonacci numbers module def fib(n): # write Fibonacci series up to n a, b = 0, 1 while b < n: print(b, end=' ') a, b = b, a+b print() def fib2(n): # return Fibonacci series up to n result = [] a, b = 0, 1 while b < n: result.append(b) a, b = b, a+b return result
模块是包含 Python 定义和声明的文件。文件名就是模块名以 扩展名.py
结尾.在模块内部,模块名 (一个字符串) 可以通过一个全局变量 __name__
取得.
>>> import fibo
在当前的符号表中,这并不导入 fibo
中定义的函数的名称,它只进入模块名称 fibo
。使用模块名称,可以访问其中的函数。
>>> fibo.fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ 'fibo'
模块可以包含可执行语句以及已定义的函数。这些语句通常用于初始化模块。只有在导入语句中第一次遇到模块名称时,才会执行。(如果文件以脚本的方式执行,它们也会运行。)
每个模块都有自己的私有符号表,它是被定义在模块中所有函数的全局符号表。因此,模块的作者可以在模块里使用全局变量,而不用担心与某个用户的全局变量有冲突。modname.itemname
这种符号指向它的函数。被导入的模块的名字放在导入模块的全局符号表中。
#从一个模块直接将名称导入到导入模块符号表中。这不会把模块名导入到本地的符号表中。 >>> from fibo import fib, fib2 >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 ''' 这种方式可以导入模块中定义的所有名字。这种方式导入除下划线 (_) 开头的所有名称。
大多数情况下Python程序员不要使用这个便利的方法,因为它会引入一系列未知的名称到解释器中,
这很可能覆盖你已经定义的一些东西。 ''' >>> from fibo import * >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
注意:
出于性能考虑,每个模块在每个解释器会话中只导入一遍。因此, 如果你更改了你的模块,你必须重启解释器——或者,如果你想用交互的方式测试你的模块,可以使用importlib.reload()
,例如import importlib; importlib.reload(modulename)
。
以脚本方式执行模块
当你用下列的方式运行一个 Python 模块
python fibo.py <arguments>
模块中的代码将会被执行,就像导入它一样,不过此时__name__
被设置为 "__main__"
。这意味着,通过在你的模块末尾添加此代码︰
if __name__ == "__main__": import sys fib(int(sys.argv[1]))
您可以使该文件可用作脚本以及可导入模块,因为解析命令行的代码只有在模块作为“main”文件执行时才会运行:
$ python fibo.py 50 1 1 2 3 5 8 13 21 34
如果模块是被导入的,将不会运行这段代码:
>>> import fibo >>>
这种方法通常用来为模块提供一个方便的用户接口,或者用来测试(例如直接运行脚本会执行一组测试用例)。
模块搜索路径
当一个叫spam
的模块被导入,解释器会先在内置模块中搜索该模块。如果没有找到,它会接着到sys.path
变量给出的目录中查找名为spam.py
的文件。sys.path
变量的初始值来自这些位置:
- 脚本所在的目录(如果没有指明文件,则为当前目录)。
-
PYTHONPATH
(一个包含目录名的列表,与shell变量PATH
的语法相同)。 - 与安装相关的默认值。
注意
在支持符号连接的文件系统中,输入的脚本所在的目录是符号连接指向的目录。换句话说,包含符号链接的目录是不添加到模块搜索路径的。(这里不太懂)
初始化后,Python程序可以修改sys.path
。脚本所在的目录被放置在搜索路径的最开始,也就是在标准库的路径之前。这意味着将会加载当前目录中的脚本,库目录中具有相同名称的模块不会被加载。除非你是有意想替换标准库,否则这应该被当成是一个错误。更多信息请参阅标准模块小节。
"编译好的"Python文件
为了加快加载模块的速度,Python在__pycache__
目录下缓存每个模块编译好的版本,名字为module.version.pyc
,其中version表示编译好的文件的格式;它一般包含Python的版本号。例如,在CPython 3.3中,spam.py编译好的版本将缓存为 __pycache__/spam.cpython-33.pyc
。这种命名约定允许由不同发布和不同版本的Python编译的模块同时存在。
Python会检查源文件和编译好的版本的修改日期,来查看它是否过期以及需要重新编译。这是完全自动化的过程。同时,编译后的模块是跨平台的,所以同一个库可以在不同架构的系统之间共享。
Python 在两种情况下不检查缓存。第一,它会始终重新编译而且不保存直接从命令行加载的模块。第二,如果没有源模块它不会检查缓存。若要支持没有源文件(只有编译版)的发布,编译后的模块必须在源目录下,并且必须没有源文件的模块。
部分高级技巧:
- 你可以在Python命令中使用
-O
或者-OO
开关来减少编译好的模块的大小。-O
开关移除assert语句,-OO
移除assert语句和__doc__字符串。因为某些程序可能会依赖于具有它们,你应该只在你知道做什么的情况下使用此选项。“优化”后的模块有一个opt-
标记,而且通常会小一些。未来的版本可能会修改优化的效果。 - 从
.pyc
文件读取的程序不会比从.py
文件读取的程序运行得更快,.pyc
文件唯一快的地方在于它们加载的速度。 compileall
模块可以为一个目录下的所有模块创建.pyc文件。- 这个过程还有更多的细节,包括决策的流程图,参见PEP 3147。
标准模块
Python 带有一个标准模块库,并发布有单独的文档叫Python 库参考手册(以下简称"库参考手册")。有些模块被直接构建在解析器里;这些操作虽然不是语言核心的部分,但是依然被内建进来,一方面是效率的原因,另一方面是为了提供访问操作系统原语,如系统调用的功能。这些模块是可配置的,也取决于底层的平台。例如,winreg
模块只在Windows系统上提供。有一个特别的模块值得注意:sys
,它内置在每一个Python解析器中。变量sys.ps1
和sys.ps2
定义了主提示符和辅助提示符使用的字符串:
>>> import sys >>> sys.ps1 '>>> ' >>> sys.ps2 '... ' >>> sys.ps1 = 'C> ' C> print('Yuck!') Yuck! C>
只有在交互式模式中,这两个变量才有定义。
变量sys.path
是一个字符串列表,它决定了模块的解释器搜索路径。它初始的默认路径来自于环境变量 PYTHONPATH
,如果 PYTHONPATH
未设置则来自于内置的默认值。你可以使用标准的列表操作修改它:
>>> import sys >>> sys.path.append('/ufs/guido/lib/python')
dir()
函数
内置函数 dir()
用来找出模块中定义了哪些名字。它返回一个排好序的字符串列表:
>>> 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()
列出当前已定义的名称:
>>> a = [1, 2, 3, 4, 5] >>> import fibo >>> fib = fibo.fib >>> dir() ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
注意它列出了所有类型的名称: 变量、 模块、 函数等。
dir()
不会列出内置的函数和变量的名称。如果你想列出这些内容,它们定义在标准模块builtins
中:
>>> 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']