6. 模块¶
如果你从Python解释器退出并再次进入,之前的定义(函数和变量)都会丢失。因此,如果你想编写一个稍长些的程序,最好使用文本编辑器为解释器准备输入并将该文件作为输入运行。这被称作编写 脚本 。随着程序变得越来越长,你或许会想把它拆分成几个文件,以方便维护。你亦或想在不同的程序中使用一个便捷的函数, 而不必把这个函数复制到每一个程序中去。
为支持这些,Python有一种方法可以把定义放在一个文件里,并在脚本或解释器的交互式实例中使用它们。这样的文件被称作 模块 ;模块中的定义可以 导入 到其它模块或者 主 模块(你在顶级和计算器模式下执行的脚本中可以访问的变量集合)。
模块是一个包含Python定义和语句的文件。文件名就是模块名后跟文件后缀 .py
。在一个模块内部,模块名(作为一个字符串)可以通过全局变量 __name__
的值获得。例如,使用你最喜爱的文本编辑器在当前目录下创建一个名为 fibo.py
的文件, 文件中含有以下内容:
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b
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解释器,并用以下命令导入该模块:
>>> 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'
如果你想经常使用某个函数,你可以把它赋值给一个局部变量:
>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
6.1. 更多有关模块的信息¶
模块可以包含可执行的语句以及函数定义。这些语句用于初始化模块。它们仅在模块 第一次 在 import 语句中被导入时才执行。 1 (当文件被当作脚本运行时,它们也会执行。)
每个模块都有它自己的私有符号表,该表用作模块中定义的所有函数的全局符号表。因此,模块的作者可以在模块内使用全局变量,而不必担心与用户的全局变量发生意外冲突。另一方面,如果你知道自己在做什么,则可以用跟访问模块内的函数的同样标记方法,去访问一个模块的全局变量,modname.itemname
。
模块可以导入其它模块。习惯上但不要求把所有 import
语句放在模块(或脚本)的开头。被导入的模块名存放在调入模块的全局符号表中。
import
语句有一个变体,它可以把名字从一个被调模块内直接导入到现模块的符号表里。例如:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这并不会把被调模块名引入到局部变量表里(因此在这个例子里,fibo
是未被定义的)。
还有一个变体甚至可以导入模块内定义的所有名称:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
This imports all names except those beginning with an underscore (_
).
注意通常情况下从一个模块或者包内调入 *
的做法是不太被接受的, 因为这通常会导致代码的可读性很差。不过,在交互式编译器中为了节省打字可以这么用。
If the module name is followed by as
, then the name
following as
is bound directly to the imported module.
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
这会和 import fibo
方式一样有效地调入模块, 唯一的区别是它以 fib
的名称存在的。
这种方式也可以在用到 from
的时候使用,并会有类似的效果:
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
注解
For efficiency reasons, each module is only imported once per interpreter
session. Therefore, if you change your modules, you must restart the
interpreter – or, if it’s just one module you want to test interactively,
use reload()
, e.g. reload(modulename)
.
6.1.1. 以脚本的方式执行模块¶
当你用下面方式运行一个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
>>>
这经常用于为模块提供一个方便的用户接口,或用于测试(以脚本的方式运行模块从而执行一些测试套件)。
6.1.2. 模块搜索路径¶
当一个名为 spam
的模块被导入的时候,解释器首先寻找具有该名称的内置模块。如果没有找到,然后解释器从 sys.path
变量给出的目录列表里寻找名为 spam.py
的文件。sys.path
初始有这些目录地址:
the directory containing the input script (or the current directory).
PYTHONPATH
(一个包含目录名称的列表,它和shell变量PATH
有一样的语法)。the installation-dependent default.
在初始化后,Python程序可以更改 sys.path
。包含正在运行脚本的文件目录被放在搜索路径的开头处, 在标准库路径之前。这意味着将加载此目录里的脚本,而不是标准库中的同名模块。 除非有意更换,否则这是错误。更多信息请参阅 标准模块。
6.1.3. “编译过的”Python文件¶
As an important speed-up of the start-up time for short programs that use a lot
of standard modules, if a file called spam.pyc
exists in the directory
where spam.py
is found, this is assumed to contain an
already-“byte-compiled” version of the module spam
. The modification time
of the version of spam.py
used to create spam.pyc
is recorded in
spam.pyc
, and the .pyc
file is ignored if these don’t match.
Normally, you don’t need to do anything to create the spam.pyc
file.
Whenever spam.py
is successfully compiled, an attempt is made to write
the compiled version to spam.pyc
. It is not an error if this attempt
fails; if for any reason the file is not written completely, the resulting
spam.pyc
file will be recognized as invalid and thus ignored later. The
contents of the spam.pyc
file are platform independent, so a Python
module directory can be shared by machines of different architectures.
给专业人士的一些小建议:
When the Python interpreter is invoked with the
-O
flag, optimized code is generated and stored in.pyo
files. The optimizer currently doesn’t help much; it only removesassert
statements. When-O
is used, all bytecode is optimized;.pyc
files are ignored and.py
files are compiled to optimized bytecode.Passing two
-O
flags to the Python interpreter (-OO
) will cause the bytecode compiler to perform optimizations that could in some rare cases result in malfunctioning programs. Currently only__doc__
strings are removed from the bytecode, resulting in more compact.pyo
files. Since some programs may rely on having these available, you should only use this option if you know what you’re doing.A program doesn’t run any faster when it is read from a
.pyc
or.pyo
file than when it is read from a.py
file; the only thing that’s faster about.pyc
or.pyo
files is the speed with which they are loaded.When a script is run by giving its name on the command line, the bytecode for the script is never written to a
.pyc
or.pyo
file. Thus, the startup time of a script may be reduced by moving most of its code to a module and having a small bootstrap script that imports that module. It is also possible to name a.pyc
or.pyo
file directly on the command line.It is possible to have a file called
spam.pyc
(orspam.pyo
when-O
is used) without a filespam.py
for the same module. This can be used to distribute a library of Python code in a form that is moderately hard to reverse engineer.The module
compileall
can create.pyc
files (or.pyo
files when-O
is used) for all modules in a directory.
6.2. 标准模块¶
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')
6.3. dir()
函数¶
内置函数 dir()
用于查找模块定义的名称。 它返回一个排序过的字符串列表:
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__',
'__stderr__', '__stdin__', '__stdout__', '_clear_type_cache',
'_current_frames', '_getframe', '_mercurial', 'api_version', 'argv',
'builtin_module_names', 'byteorder', 'call_tracing', 'callstats',
'copyright', 'displayhook', 'dont_write_bytecode', 'exc_clear', 'exc_info',
'exc_traceback', 'exc_type', 'exc_value', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'gettotalrefcount', 'gettrace', 'hexversion',
'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules',
'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'py3kwarning', 'setcheckinterval', 'setdlopenflags', 'setprofile',
'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion',
'version', 'version_info', 'warnoptions']
如果没有参数,dir()
会列出你当前定义的名称:
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', '__package__', 'a', 'fib', 'fibo', 'sys']
注意:它列出所有类型的名称:变量,模块,函数,等等。
dir()
does not list the names of built-in functions and variables. If you
want a list of those, they are defined in the standard module
__builtin__
:
>>> import __builtin__
>>> dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError',
'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning',
'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError',
'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError',
'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True',
'TypeError', 'UnboundLocalError', 'UnicodeDecodeError',
'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError',
'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning',
'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__',
'__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring',
'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr',
'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright',
'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval',
'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset',
'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license',
'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next',
'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit',
'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round',
'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super',
'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
6.4. 包¶
包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法。 例如,模块名 A.B
表示 A
包中名为 B
的子模块。正如模块的使用使得不同模块的作者不必担心彼此的全局变量名称一样,使用加点的模块名可以使得 NumPy 或 Pillow 等多模块软件包的作者不必担心彼此的模块名称一样。
假设你想为声音文件和声音数据的统一处理,设计一个模块集合(一个“包”)。由于存在很多不同的声音文件格式(通常由它们的扩展名来识别,例如:.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
...
当导入这个包时,Python搜索 sys.path
里的目录,查找包的子目录。
The __init__.py
files are required to make Python treat the directories
as containing packages; this is done to prevent directories with a common name,
such as string
, from unintentionally hiding valid modules that occur later
on the module search path. In the simplest case, __init__.py
can just be
an empty file, but it can also execute initialization code for the package or
set the __all__
variable, described later.
包的用户可以从包中导入单个模块,例如:
import sound.effects.echo
这会加载子模块 sound.effects.echo
。但引用它时必须使用它的全名。
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
导入子模块的另一种方法是
from sound.effects import echo
这也会加载子模块 echo
,并使其在没有包前缀的情况下可用,因此可以按如下方式使用:
echo.echofilter(input, output, delay=0.7, atten=4)
另一种形式是直接导入所需的函数或变量:
from sound.effects.echo import echofilter
同样,这也会加载子模块 echo
,但这会使其函数 echofilter()
直接可用:
echofilter(input, output, delay=0.7, atten=4)
请注意,当使用 from package import item
时,item可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数,类或变量。 import
语句首先测试是否在包中定义了item;如果没有,它假定它是一个模块并尝试加载它。如果找不到它,则引发 ImportError
异常。
相反,当使用 import item.subitem.subsubitem
这样的语法时,除了最后一项之外的每一项都必须是一个包;最后一项可以是模块或包,但不能是前一项中定义的类或函数或变量。
6.4.1. 从包中导入 *¶
当用户写 from sound.effects import *
会发生什么?理想情况下,人们希望这会以某种方式传递给文件系统,找到包中存在哪些子模块,并将它们全部导入。这可能需要很长时间,导入子模块可能会产生不必要的副作用,这种副作用只有在显式导入子模块时才会发生。
唯一的解决方案是让包作者提供一个包的显式索引。import
语句使用下面的规范:如果一个包的 __init__.py
代码定义了一个名为 __all__
的列表,它会被视为在遇到 from package import *
时应该导入的模块名列表。在发布该包的新版本时,包作者可以决定是否让此列表保持更新。包作者如果认为从他们的包中导入 * 的操作没有必要被使用,也可以决定不支持此列表。例如,文件 sound/effects/__init__.py
可以包含以下代码:
__all__ = ["echo", "surround", "reverse"]
这意味着 from sound.effects import *
将导入 sound
包的三个命名子模块。
如果没有定义 __all__
,from sound.effects import *
语句 不 会从包 sound.effects
中导入所有子模块到当前命名空间;它只确保导入了包 sound.effects
(可能运行任何在 __init__.py
中的初始化代码),然后导入包中定义的任何名称。这包括 __init__.py`
定义的任何名称(以及显式加载的子模块)。它还包括由之前的 import
语句显式加载的包的任何子模块。思考下面的代码:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
在这个例子中, echo
和 surround
模块是在执行 from...import
语句时导入到当前命名空间中的,因为它们定义在 sound.effects
包中。(这在定义了 __all__
时也有效。)
虽然某些模块被设计为在使用 import *
时只导出遵循某些模式的名称,但在生产代码中它仍然被认为是不好的做法。
请记住,使用 from package import specific_submodule
没有任何问题! 实际上,除非导入的模块需要使用来自不同包的同名子模块,否则这是推荐的表示法。
6.4.2. 子包参考¶
The submodules often need to refer to each other. For example, the
surround
module might use the echo
module. In fact, such
references are so common that the import
statement first looks in the
containing package before looking in the standard module search path. Thus, the
surround
module can simply use import echo
or from echo import
echofilter
. If the imported module is not found in the current package (the
package of which the current module is a submodule), the import
statement looks for a top-level module with the given name.
当包被构造成子包时(与示例中的 sound
包一样),你可以使用绝对导入来引用兄弟包的子模块。例如,如果模块 sound.filters.vocoder
需要在 sound.effects
包中使用 echo
模块,它可以使用 from sound.effects import echo
。
Starting with Python 2.5, in addition to the implicit relative imports described
above, you can write explicit relative imports with the from module import
name
form of import statement. These explicit relative imports use leading
dots to indicate the current and parent packages involved in the relative
import. From the surround
module for example, you might use:
from . import echo
from .. import formats
from ..filters import equalizer
Note that both explicit and implicit relative imports are based on the name of
the current module. Since the name of the main module is always "__main__"
,
modules intended for use as the main module of a Python application should
always use absolute imports.