资讯专栏INFORMATION COLUMN

python基础教程:模块高级技巧

JasinYip / 2132人阅读

摘要:标准模块附带了一个标准模块库。它返回一个如果调用不传递参数,则列出当前已经定义的所有名字用可以查看所有的内置类型变量函数等,方法是借助标准模块模块高级技巧总结的搜索路径,顺序一定要搞得清编译后的文件内置函数查看模块定义的名字。

上一节,我们讲解了Python模块的基础知识,这一节我们继续深入了解模块的更多知识,从而让大家全面了解、掌握和运用模块到我们实际的编程中。

在上一节中有一句话“接着我们在这个文件所在目录运行Python解释器IPython”,不知道大家还记不记得。这就话背后隐含的意思是,在这个文件(模块)目录下,我们才可以import到这个模块,否则会报错,说找不到这个模块。这里,就涉及到了Python模块的搜索路径。

Python模块的搜索路径

当一个名为mylib的模块被导入时,解释器首先搜索内置模块是不是有该名字的模块。
如果没有找到,接着搜索sys.path列出的目录下面是不是有名为mylib的模块。

sys.path的初始化按以下几个路径的顺序:
**(1)包含输入脚本的目录,如果没有输入脚本则是当前目录;
(2)环境变量PYTHONPATH(一个目录名称的列表);
(3)Python库的安装目录。**

下面我们来验证一下sys.path所包含的路径,编写一个Python文件initpath.py如下:

# Author: veelion
# file: initpath.py

import sys
print("
".join(sys.path))

命令行下运行:python3 initpath.py得到如下结果:

$ python mylib.py
/home/veelion/p2/tutorial/md_Python/codes
/home/veelion/.virtualenvs/py3.7/lib/python37.zip
/home/veelion/.virtualenvs/py3.7/lib/python3.7
/home/veelion/.virtualenvs/py3.7/lib/python3.7/lib-dynload
/usr/lib/python3.7
/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages

我们可以发现,initpath.py所在的目录是sys.path列表的第一个元素。符合上面三条原则的顺序。

接下来我们通过交互式Python解释器来看看sys.path,运行CPython解释器再导入sys:

>>> import sys
>>> sys.path
["", "/home/veelion/.virtualenvs/py3.7/lib/python37.zip", "/home/veelion/.virtualenvs/py3.7/lib/python3.7", "/home/veelion/.virtualenvs/py3.7/lib/python3.7/lib-dynload", "/usr/lib/python3.7", "/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages"]

细心的小猿可以发现,sys.path的第一项是个空字符串,和运行脚本方式下的第一项——当前路径不一样。为什么会是空字符串呢?

这是因为,当交互式运行Python解释器时(或者脚本是从标注输入读取的),可以认为传给解释器的脚本文件路径为空,那么就把sys.path[0]设置为空字符串,它告诉Python搜索模块时先从当前文件夹开始。

以上两种方法验证的sys.path都符合预期,然而IPython有点例外。

In [1]: import sys

In [2]: sys.path
Out[2]: 
["/home/veelion/.virtualenvs/py3.7/bin",
 "/home/veelion/.virtualenvs/py3.7/lib/python37.zip",
 "/home/veelion/.virtualenvs/py3.7/lib/python3.7",
 "/home/veelion/.virtualenvs/py3.7/lib/python3.7/lib-dynload",
 "/usr/lib/python3.7",
 "",
 "/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages",
 "/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages/IPython/extensions",
 "/home/veelion/.ipython"]

IPython 并没有把当前路径放在第一项。这样就会导致你写的模块与系统模块重名时,它import的是系统模块而不是你写的模块,而前面两种方式就是导入你写的模块而非系统模块。这一点在使用IPython时要格外注意。

注意你可以在程序中修改sys.pathsys.path是一个Python的列表结构,我们可以像修改列表那样修改它,增加、删除、修改路径顺序。比如,可以通过sys.path.insert(0, "my-module-path")来把我们自己写的模块的路径放到搜索路径的最前面,优先搜索自己的模块。

编译后的Python文件:*pyc

为了加速模块的加载时间,Python会缓存已经编译好的模块,并把它们放在与模块同级目录下的__pycache__文件夹下面,编译好的模块的命名方式为:module.version.pyc,其中的version包含Python的版本号。比如:

$ ls __pycache__/
m1.cpython-36.pyc  m2.cpython-36.pyc

cpython-36就是编译这个模块的Python信息:用CPython 3.6 进行编译的。这种命名方式方便不同版本的Python编译的模块同时存在而不造成冲突。

Python在两种情况下不检查缓存。
其一,它总是重新编译并且不存储直接从命令行加载的模块的结果。
其二,如果没有模块源码文件,它不会检查缓存。要支持非源(仅编译)分发,已编译的模块必须位于源码目录中,并且不得有模块源码。

举个例子理解一下这两点:
(1)如果在命令行下运行python m1.py,Python总是从新编译m1.py,但不会保存pyc文件,因为每次都有重新编译就没必要保存了。
(2)如果我们导入m1模块时,搜索路径目录下只有m1.pyc而没有m1.py文件,那就直接导入m1.pyc。这种方式适合把编译好的pyc发布给其他人而不是给它们源代码,使用这种方式时,把.pyc文件从__pycache__中拷贝到.py文件相同的目录下并删掉.py文件即可。

Python模块的高级技巧

(1)模块compileall可以把一个文件夹下所有的py文件编译成.pyc文件。
它的使用很简单,命令行运行的格式如下:
python -m compileall 文件夹或文件名
更多选项可以通过:python -m compileall -h查看。

(2)编译成.pyc文件时,可以给Python命令两个选项:-O-OO,使得编译后的文件更小。
-O 去除assert语句;
-OO 去除assert语句和__doc__ string
根据情况来使用这两个选项,用compileall编译文件时加这个选项就是这样子的:
python -O -m compileall 文件夹或文件名

生成的pyc文件名称里面有opt-标签,-O的标签是opt--OO的标签就是opt-2。比如:

$ ls -F -1 __pycache__/
m1.cpython-36.opt-1.pyc
m1.cpython-36.opt-2.pyc
m1.cpython-36.pyc

(3).pyc.py文件都不会使程序运行得更快(不会提高运行速度)。但是,.pyc文件能使加载速度更快,因为少了编译的过程。

Python标准模块

Python附带了一个标准模块库。其中一些模块内置在解释器中,它们提供对不属于语言核心但仍然内置的操作的访问,以提高效率或提供对系统调用等操作系统原语的访问。这些模块的集合是一个配置选项,它也取决于底层平台。例如,winreg模块仅在Windows系统上提供。一个值得注意的模块是sys,它内置于每个Python解释器中。

Python的标注模块会在我们今后的编程中不断遇到和使用,具体的学习可以在今后用到时再学习。你需要记住的一点是:当你写Python代码需要某些基本功能时,一定要先找找看是否已经有标准模块存在,是否已经有人写好了包含这些功能的模块,最后才要觉得自己要不要实现这些功能。

Python内置函数dir()

dir()用来查看模块里面定义的名字,包括:变量名,模块名,函数名等等。
它返回一个list:

In [5]: import my_first_module

In [6]: dir(my_first_module)
Out[6]: 
["MY_NAME",
 "__builtins__",
 "__cached__",
 "__doc__",
 "__file__",
 "__loader__",
 "__name__",
 "__package__",
 "__spec__",
 "my_add",
 "my_print"]

如果调用dir()不传递参数,则列出当前已经定义的所有名字:

In [1]: import my_first_module

In [2]: dir()
Out[2]: 
["In",
 "Out",
 "_",
 "__",
 "___",
 "__builtin__",
 "__builtins__",
 "__doc__",
 "__loader__",
 "__name__",
 "__package__",
 "__spec__",
 "_dh",
 "_i",
 "_i1",
 "_i2",
 "_ih",
 "_ii",
 "_iii",
 "_oh",
 "exit",
 "get_ipython",
 "my_first_module",
 "quit"]

用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", "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", "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"]
Python模块高级技巧总结

(1)Python的搜索路径,顺序一定要搞得清;
(2)编译后的.pyc文件;
(3)dir()内置函数查看模块定义的名字。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43799.html

相关文章

  • 编程书单:十本Python编程语言的入门书籍

    摘要:本文与大家分享一些编程语言的入门书籍,其中不乏经典。全书贯穿的主体是如何思考设计开发的方法,而具体的编程语言,只是提供一个具体场景方便介绍的媒介。入门入门容易理解而且读起来幽默风趣,对于编程初学者和语言新手而言是理想的书籍。 本文与大家分享一些Python编程语言的入门书籍,其中不乏经典。我在这里分享的,大部分是这些书的英文版,如果有中文版的我也加上了。有关书籍的介绍,大部分截取自是官...

    desdik 评论0 收藏0
  • 史上最详细Python学习路线-从入门到精通,只需90天

    摘要:针对的初学者,从无到有的语言如何入门,主要包括了的简介,如何下载,如何安装,如何使用终端,等各种开发环境进行开发,中的语法和基本知识概念和逻辑,以及继续深入学习的方法。 ...

    gghyoo 评论0 收藏0
  • SegmentFault 技术周刊 Vol.30 - 学习 Python 来做一些神奇好玩的事情吧

    摘要:学习笔记七数学形态学关注的是图像中的形状,它提供了一些方法用于检测形状和改变形状。学习笔记十一尺度不变特征变换,简称是图像局部特征提取的现代方法基于区域图像块的分析。本文的目的是简明扼要地说明的编码机制,并给出一些建议。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 开始之前,我们先来看这样一个提问: pyth...

    lifesimple 评论0 收藏0
  • SegmentFault 技术周刊 Vol.40 - 2018,来学习一门新的编程语言吧!

    摘要:入门,第一个这是一门很新的语言,年前后正式公布,算起来是比较年轻的编程语言了,更重要的是它是面向程序员的函数式编程语言,它的代码运行在之上。它通过编辑类工具,带来了先进的编辑体验,增强了语言服务。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不觉已经到来了,总结过去的 2017,相信小伙们一定有很多收获...

    caspar 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<