Home > Backend Development > Python Tutorial > Python Manual Module

Python Manual Module

巴扎黑
Release: 2017-06-23 16:29:36
Original
1464 people have browsed it

[Translation]The Python Tutorial#Modules

6. Modules

If you exit and re-enter the Python interpreter, the previously defined names (functions and variables) are lost . Therefore, if you want to write longer programs, it is better to use a text editor to prepare input to the interpreter, using files as input instead. This is also called creating a script. As your program grows longer, you may split the program into several files for ease of maintenance reasons. You may also want to use a useful function in multiple programs without copying its definition into each program.

To support these requirements, Python provides a way to put definitions into a file and use them in a script or interactive instance of the interpreter. Such a file is called a module; definitions in the module can be imported into other modules or into the main module (the set of variables accessible in top-level scripts and calculation modes).

A module is a file containing Python definitions and statements. The file name is the module name and has the .py suffix. Within a module, the module's name (as a string) is available as the value of the global variable __name__. For example, use your favorite text editor to create a fibo.py file in the current directory with the following content:

# Fibonacci numbers moduledef fib(n):    # write Fibonacci series up to na, b = 0, 1while b < n:print(b, end=&#39; &#39;)
        a, b = b, a+bprint()def fib2(n):   # return Fibonacci series up to nresult = []
    a, b = 0, 1while b < n:
        result.append(b)
        a, b = b, a+breturn result
Copy after login

Enter the Python interpreter and import using the following command This module:

>>> import fibo
Copy after login

This operation does not import the name of the function defined in fibo into the current symbol table; it only imports the name of the module fibo. The function can be accessed using the module name:

>>> 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__&#39;fibo&#39;
Copy after login

If you want to use the function frequently, you can assign it to a local name:

>>> fib = fibo.fib>>> fib(500)1 1 2 3 5 8 13 21 34 55 89 144 233 377
Copy after login

6.1 More on Modules

Modules can contain both executable statements and function definitions. Executable statements are used to initialize modules. When the module name appears in an import statement, these executable statements are executed only once[1]. (If the file is used as a script, these executables will also be executed)

Each module has its own private symbol table, which is used as a global symbol table by all functions defined in the module. Therefore, module authors can use these global variables without worrying about accidental name conflicts with those used for global variables. On the other hand, if you know what you're doing, you can reference the module's global variables the same way you reference functions, modname.itemname.

Modules can reference other modules. It is a good practice to place all import statements at the beginning of the module (or script), but it is not mandatory. The imported module name will be placed in the current module's global symbol table.

There is a variant of the import statement that directly imports the module name into the symbol table of the current module. For example:

>>> from fibo import fib, fib2>>> fib(500)1 1 2 3 5 8 13 21 34 55 89 144 233 377
Copy after login

The above will not introduce the name of the module (fibo will not be defined in the above example).

There is even a way to import all names defined in a module:

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

This method imports all names that do not start with an underscore _ . In most cases, Python programmers will not use this method, because it will import an unknown set of names into the interpreter, and perhaps block some names that are already defined.

It should be noted that in practice, importing from a module or package is usually discouraged, because it will reduce the readability of the program. However, it is possible to use it in an interactive environment to reduce typing.

Note: For performance reasons, each module is imported only once in an interpreter session. Therefore, if the module is changed, the interpreter must be restarted; if you only want to interactively test a module, use importlib.reload(), for example: import importlib; importlin.reload(modulename)

6.1.1 Executing modules as scripts

When running a Python module using the following command:

python fibo.py <arguments>
Copy after login

Code in the module will be executed as if the module was imported, but now __name__ is set to __main__. This means that the following code will be added to the end of the module:

if __name__ == "__main__":import sys
    fib(int(sys.argv[1]))
Copy after login

The module is executed as a script and can also be imported as a module, because only when the module is executed as a mian file When the module is imported, the code that parses the command line will not be executed:

$ python fibo.py 501 1 2 3 5 8 13 21 34
Copy after login

If the module is imported, the code will not be executed:

>>> import fibo>>>
Copy after login

这可以用来为使用者提供一个模块用户接口的使用约定,也可以用作测试(模块作为脚本时执行测试用例)

6.1.2 The Module Search Path

当模块spam被导入时,解释器首先搜索built-in模块。如果没有找到,解释器在变量sys.path提供的路径列表中搜索名为spam.py的文件。sys.path从下列位置初始化:

  • 包含输入脚本的目录(或者没有指定文件时的当前目录)

  • PYTHONPATH(目录名字集合,与shell环境变量PATH相似,也是环境变量)

  • 安装默认目录

注意: 在支持符号链接的文件系统,包含输入脚本的目录是符号链接指向的目录。也就是说包含符号链接的目录不会被加入到搜索路径中。

初始化后,Python程序可以修改sys.path。包含执行脚本的目录被放置到搜索路径的开始,在标准库路径之前。这意味着该目录中的脚本会被加载,而标准库目录中的同名模块不会被加载。这会引发错误,除非是有意替换标准库的模块。阅读Standard Modules获取更多信息。 (译注:自定义的模块不应与标准模块重名,否则标准模块会被覆盖。)

6.1.3 “Compiled” Python files

为加速模块加载,Python会在__pycache__目录中缓存每个模块的编译版本,缓存文件名为module.version.pycversion编码了被编译文件的版本;通常包含了Python的版本号。例如,在CPython release 3.3中,文件spam.py的编译版本会被缓存为__pycache__/spam.cpython-33.pyc。这种命名约定允许来自不同Python发行版本的模块得以共存。

Python检查源文件的修改日期与编译版本,来确定编译版本是否过期,是否需要重新编译。这是一个完全自动化的过程。另外,编译模块是平台独立的,因此异构系统可以共享相同的库。

Python不会检查在两个环境中的缓存。首先,Python总是重新编译,并且不会存储直接从命令行加载的模块的结果。其次,如果没有源模块,Python不检查缓存。若要支持无源文件(只有编译版本)分布,那么编译的模块必须放在源文件目录中,并且源模块必需不存在。

给专家的建议:

  • 可以在命令行使用-O或者-OO开关来减少编译模块的大小。-O参数移除assert语句,-OO参数同时移除assert语句和__doc__字符串。由于一些程序依赖这些变量,那么只有当你确认你要这么做时,才能使用这两个参数。“优化的”模块有一个opt-标签并且通常更小。未来的发型版本可能改变优化的影响。

  • .pyc文件中读取的程序不会比从.py文件读取的程序跑得快;.pyc文件快的地方在于加载。

  • compileall模块可以为目录中的所有模块创建.pyc文件。

  • PEP 3147中有关系这点的更多信息,包括一个决策流程

6.2 Standard Modules

Python提供了标准模块库,在独立文档中描述,名为Python Library Reference(以后叫做Library Reference)。有一些模块内嵌入解释器中,这些模块不是语言核心的一部分,但是它们是内嵌的,这既是为性能考虑,也提供了访问如系统调用般的操作系统原生接口的方式。这些模块集合依赖底层平台的配置选项。例如winreg模块只在Windows系统中提供。一个特殊的模块值得注意:sys,这个模块内嵌在所有Python解释器中。变量sys.ps1sys.ps2定义了主提示符和辅助提示符的字符串:

>>> import sys>>> sys.ps1&#39;>>> &#39;>>> sys.ps2&#39;... &#39;>>> sys.ps1 = &#39;C> &#39;C> print(&#39;Yuck!&#39;)
Yuck!C>
Copy after login

只有当解释器以交互模式运行才会定义这两个变量。

变量sys.path是决定解释器模块搜索路径的字符列表。该变量从环境变量PYTHONPATH,或者内置默认路径(PYTHONPATH未指定时)初始化。可以使用标准list操作修改它的值:

>>> import sys>>> sys.path.append(&#39;/ufs/guido/lib/python&#39;)
Copy after login

6.3 The dir() Function

内嵌函数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']
Copy after login

不带参数使用dir()函数,会列出当前作用域的全部名字:

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

需要注意该函数列出所有类型的名字:变量,模块,函数,等等。

dir()不会列出内嵌函数和变量的名字。如果希望列出,这些名字定义在标准模块builtins中:

>>> import builtins>>> dir(builtins)  
[&#39;ArithmeticError&#39;, &#39;AssertionError&#39;, &#39;AttributeError&#39;, &#39;BaseException&#39;, &#39;BlockingIOError&#39;, &#39;BrokenPipeError&#39;, &#39;BufferError&#39;, &#39;BytesWarning&#39;, &#39;ChildProcessError&#39;, &#39;ConnectionAbortedError&#39;, &#39;ConnectionError&#39;, &#39;ConnectionRefusedError&#39;, &#39;ConnectionResetError&#39;, &#39;DeprecationWarning&#39;, &#39;EOFError&#39;, &#39;Ellipsis&#39;, &#39;EnvironmentError&#39;, &#39;Exception&#39;, &#39;False&#39;, &#39;FileExistsError&#39;, &#39;FileNotFoundError&#39;, &#39;FloatingPointError&#39;, &#39;FutureWarning&#39;, &#39;GeneratorExit&#39;, &#39;IOError&#39;, &#39;ImportError&#39;, &#39;ImportWarning&#39;, &#39;IndentationError&#39;, &#39;IndexError&#39;, &#39;InterruptedError&#39;, &#39;IsADirectoryError&#39;, &#39;KeyError&#39;, &#39;KeyboardInterrupt&#39;, &#39;LookupError&#39;, &#39;MemoryError&#39;, &#39;NameError&#39;, &#39;None&#39;, &#39;NotADirectoryError&#39;, &#39;NotImplemented&#39;, &#39;NotImplementedError&#39;, &#39;OSError&#39;, &#39;OverflowError&#39;, &#39;PendingDeprecationWarning&#39;, &#39;PermissionError&#39;, &#39;ProcessLookupError&#39;, &#39;ReferenceError&#39;, &#39;ResourceWarning&#39;, &#39;RuntimeError&#39;, &#39;RuntimeWarning&#39;, &#39;StopIteration&#39;, &#39;SyntaxError&#39;, &#39;SyntaxWarning&#39;, &#39;SystemError&#39;, &#39;SystemExit&#39;, &#39;TabError&#39;, &#39;TimeoutError&#39;, &#39;True&#39;, &#39;TypeError&#39;, &#39;UnboundLocalError&#39;, &#39;UnicodeDecodeError&#39;, &#39;UnicodeEncodeError&#39;, &#39;UnicodeError&#39;, &#39;UnicodeTranslateError&#39;, &#39;UnicodeWarning&#39;, &#39;UserWarning&#39;, &#39;ValueError&#39;, &#39;Warning&#39;, &#39;ZeroDivisionError&#39;, &#39;_&#39;, &#39;__build_class__&#39;, &#39;__debug__&#39;, &#39;__doc__&#39;, &#39;__import__&#39;, &#39;__name__&#39;, &#39;__package__&#39;, &#39;abs&#39;, &#39;all&#39;, &#39;any&#39;, &#39;ascii&#39;, &#39;bin&#39;, &#39;bool&#39;, &#39;bytearray&#39;, &#39;bytes&#39;, &#39;callable&#39;, &#39;chr&#39;, &#39;classmethod&#39;, &#39;compile&#39;, &#39;complex&#39;, &#39;copyright&#39;, &#39;credits&#39;, &#39;delattr&#39;, &#39;dict&#39;, &#39;dir&#39;, &#39;divmod&#39;, &#39;enumerate&#39;, &#39;eval&#39;, &#39;exec&#39;, &#39;exit&#39;, &#39;filter&#39;, &#39;float&#39;, &#39;format&#39;, &#39;frozenset&#39;, &#39;getattr&#39;, &#39;globals&#39;, &#39;hasattr&#39;, &#39;hash&#39;, &#39;help&#39;, &#39;hex&#39;, &#39;id&#39;, &#39;input&#39;, &#39;int&#39;, &#39;isinstance&#39;, &#39;issubclass&#39;, &#39;iter&#39;, &#39;len&#39;, &#39;license&#39;, &#39;list&#39;, &#39;locals&#39;, &#39;map&#39;, &#39;max&#39;, &#39;memoryview&#39;, &#39;min&#39;, &#39;next&#39;, &#39;object&#39;, &#39;oct&#39;, &#39;open&#39;, &#39;ord&#39;, &#39;pow&#39;, &#39;print&#39;, &#39;property&#39;, &#39;quit&#39;, &#39;range&#39;, &#39;repr&#39;, &#39;reversed&#39;, &#39;round&#39;, &#39;set&#39;, &#39;setattr&#39;, &#39;slice&#39;, &#39;sorted&#39;, &#39;staticmethod&#39;, &#39;str&#39;, &#39;sum&#39;, &#39;super&#39;, &#39;tuple&#39;, &#39;type&#39;, &#39;vars&#39;, &#39;zip&#39;]
Copy after login

6.4 Packages

包是使用“圆点模块名”结构化Python模块名字空间的方式。例如,模块名A.B表示包A中的子模块B。就像模块使得不同模块的作者免于担忧每个模块的全局名字一样,圆点模块名的使用使得多模块包(如NumPy或者Python图像库)的作者免于担忧每个模块的名字。

假设需要为统一音频文件和音频数据的处理设计一个模块的集合(包)。有许多不同的音频文件格式(通常通过扩展名辨认,如.wav, .aiff, .au),因此需要为不同文件格式的转换创建和维护一个持续增长的模块集合。也存在许多对音频数据不同的操作(例如混合,增加回声,增加均衡器函数,创建人造立体效果),因此需要额外编写执行这些操作的大量模块。以下是包的可能结构(以层级文件结构来表示):

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
              ...
Copy after login

导入包时,Python搜索sys.path提供的路径寻找包子目录。

为使Python将普通目录看做包,目录中必须包含__init__.py文件。这样做是为了避免普通的目录名(如string)将以后会出现在模块搜索路径中的有效模块无意识的隐藏掉。最简单的情况是,__init__.py可以是一个空文件,但是它也可以包含可执行的初始化包的代码或者设置__all__变量,后面讲述。

包的用户可以从包中导入独立的模块:

import sound.effects.echo
Copy after login

这将加在子模块sound.effects.echo。必须使用全名引用:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
Copy after login

导入子模块可选方式:

from sound.effects import echo
Copy after login

以上也加载子模块echo,不使用包前缀引用模块,因此可以像下面一样使用:

echo.echofilter(input, output, delay=0.7, atten=4)
Copy after login

另外的方式是直接导入需要的函数或者变量:

from sound.effects.echo import echofilter
Copy after login

同样的,这将加在子模块echo,但使函数echofilter()直接可用:

echofilter(input, output, delay=0.7, atten=4)
Copy after login

注意当使用from package import item时,item可以使子模块(子包),也可以是包内定义的其他名字,如函数,类或者变量。import语句首先测试要导入的项是否在包中存在;如果不存在,Python假设这个项是模块并尝试加载它。如果最后寻找失败,ImportError异常抛出。

相对的,使用import item.subitem.subsubitem时,除了最后一项,每一项都必须是包;最后一项可以是模块或者包但是不能是前面的项中定义的类,函数或者变量。

6.4.1 Importing * From a Package

使用from sound.effects import *会发生什么?理想情况下,总是期望在文件系统中找出所有子模块,并全部导入。全部导入会耗费很长时间,并且导入子模块可能会有不期待的副作用,这些副作用应该在显式导入时发生。

唯一的解决方案是包作者提供一个包的显式索引。import语句遵循以下约定:如果包的__init__.py代码中定义了名为__all__的变量,那么使用from package import *时会导入该变量指定的所有模块。当包的新版本发布时,由包作者负责更新列表__all__。如果包作者不希望可以使用from package import *导入包中的模块,也可以不支持__all__。 例如,文件sound/effects/__init__.py可能包含以下代码:

__all__ = ["echo", "surround", "reverse"]
Copy after login

这意味着from sound.effects import *会导入sound包中指定的三个模块。

如果__all__没有定义,语句from sound.effects import *不会将包sound.effects中的子模块全部倒入到当前名字空间中,只保证包sound.effects被导入了(可能会运行__init__.py中的初始化代码)并且导入任意在包中定义的名字。包括在__init__.py中定义的任意名字(以及显式加载的子模块)。也会包括前面的import语句显式加载的任意包子模块。考虑如下代码:

import sound.effects.echoimport sound.effects.surroundfrom sound.effects import *
Copy after login

这个例子中,echosurround模块被导入到当前名字空间中,因为执行from... import时,它们已经定义在sound.effects包中定义了。(定义了__all__时同样有效)

尽管使用import *时只有符合特定模式的名字会被导出,但仍然不建议在生产代码中使用。

记住,使用form Package import specific_submodle没有错误。实际上,这是推荐的方法,除非当前模块需要使用其他包中的同名模块。

6.4.2 Intra-package References

当包中包含了子包结构(就如例子中的sound包),可以使用绝对导入的方式引用兄弟包中的子模块。例如,如果模块sound.filters.vocoder需要使用包sound.effects中的echo模块,可以使用from sound.effects import echo

也可以使用from modul import name语句来相对导入模块。这种方式使用点.指示当前包和相对导入中涉及的父包。以surround模块为例:

from . import echofrom .. import formatsfrom ..filters import equalizer
Copy after login

相对导入基于当前模块的名字。由于主模块的名字总是__main__,要当做Python应用主模块使用的模块必须总是使用绝对导入的方式。

6.4.3 Packages in Multiple Directories

包还支持一个特殊属性,__path__。在__init__.py中的代码执行之前,属性__path__被初始化为一个列表,这个列表包含了持有该__init__.py文件的目录的路径。该变量可修改,这样做会影响将来的对包内模块和子包的搜索。

然而这个特性不总是需要的,它可以用来扩展包的模块集合

Footnotes

[1] 实际上,函数定义也是可“执行”的“语句”;模块级别的函数执行将函数的名字放置到模块的全局符号表中

The above is the detailed content of Python Manual Module. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template