Skip to content

Instantly share code, notes, and snippets.

@oiuww09fn
Last active August 29, 2015 14:04
Show Gist options
  • Save oiuww09fn/5287b1d2bb53f516d9e9 to your computer and use it in GitHub Desktop.
Save oiuww09fn/5287b1d2bb53f516d9e9 to your computer and use it in GitHub Desktop.
python module and package

模块

通常来说一个模块对应一个python源码文件,可通过sys.modules查看当前python解释器可导入的模块。

In [16]: sys.modules
{...
'sys': <module 'sys' (built-in)>,
'sysconfig': <module 'sysconfig' from '/usr/lib/python2.7/sysconfig.pyc'>,
'tempfile': <module 'tempfile' from '/usr/lib/python2.7/tempfile.pyc'>,
'textwrap': <module 'textwrap' from '/usr/lib/python2.7/textwrap.pyc'>,
'thread': <module 'thread' (built-in)>,
'threading': <module 'threading' from '/usr/lib/python2.7/threading.pyc'>,
'time': <module 'time' (built-in)>,
'token': <module 'token' from '/usr/lib/python2.7/token.pyc'>,
'tokenize': <module 'tokenize' from '/usr/lib/python2.7/tokenize.pyc'>,
...}

导入模块

import
from...import
import...as
from...import...as
__import__()  # import其实调用的是该方法
reload()  # 模块源码变动后可用此方法重新导入模块, 参数不能是字符串,必须是不包含引号的模块名。

注:不推荐用"import *",因为这样会导入不需要的对象,还可能与当前模块中成员命名发生冲突。 (可以试试python解释器里导入from sys import *, 然后exit

模块搜索路径

  • 当前目录
  • PYTHONPATH指定目录
  • python标准库
  • 第三方模块(site-packages下)

可通过sys.path查看python搜索路径,sys.path是一个列表,可以通过append添加自定义搜索路径,也可以删除某路径(参照列表操作)。

sys.path.append("a path")

python模块第一次被导入的时候会生成py[co]字节码文件。pyc文件是平台无关的,运行的时候再由python解释器生成机器码。由于python程序执行的时候读的是pyc字节码文件,所以发布程序的时候如果不想被人看到代码可以只发布字节码文件。(注:pyo是优化后的字节码文件,可用python -O -m modulename生成)

使用import 导入的时候实际导入的是目标模块名字空间中的成员(没带下滑线的),所以如果目标模块导入了其它模块中的成员,这些成员也会被导入到当前模块中。解决该问题可用__all__,显式指定可用导出的成员。如果定义了__all__,想导入不在__all__中的成员,或者想导入私有成员,只能显示导入。 all = ["hello"]

注:还有一些更深入的模块导入方面的问题,参照《python学习笔记》

模块属性

  • __name__:模块名称
  • __file__:模块对应文件(为什么sys没有该属性TODO)
  • __doc__:模块文档字符串
  • __dict__:模块名字空间:(和vars(modulename)返回一样)

Python包

包含__init__.py的目录,就是python包(我是这么认为的)。

在导入包或者包里面的模块的时候首先会执行__init__.py,它可用于包环境初始化或存放包的文档字符串等信息。通常__init__.py文件就是一个空文件。

一个包里可包含多个模块,也可以包含子包。

包的引入可以解决如下问题:(摘自《Python核心编程》第二版321页)

  • 为平坦的名称空间加入有层次的组织结构。
  • 允许程序员把有联系的模块组合到一起。
  • 允许分发者使用目录结构而不是一大堆混乱的文件。
  • 帮助解决有冲突的模块名称。

导入包(参照导入模块)

**注:**在python2中包的模块中导入其它模块默认是先搜索本包中的模块(相对导入),然后再搜索包的搜索路径中的模块(绝对导入)。但python3中默认搜索的是搜索路径中的模块(绝对导入)。python3中如想用相对导入,需用点号from .module import func。显示的使用相对导入可避免因模块名字冲突造成的导入错误。

test
    __init__.py
    main.py
    string.py

如上,如果在main中想导入标准库的stringimport string,可根据导入规则,先搜到的是本目录中的string模块,于是会发生导入错误。python3就不会出这种问题,因为是绝对导入。如果想在python3中导入本目录的string,需用import .string

包的目录结构

参照robotframework

第三方包安装

安装工具

虚拟环境

# pip settings for virtualenv
# Installation: pip install virtualenv

#  Require an activated virtualenv
export PIP_REQUIRE_VIRTUALENV=true
# Auto switch to virtualenv
export PIP_RESPECT_VIRTUALENV=true

# virtualenvwrapper setting
# Installation: pip install virtualenvwrapper
# USAGE:
#     workon                  list env
#     workon       <envname>  start/switch env
#     mkvirtualenv <envname>  mk env
#     rmvitualenv  <envname>  rm env
#     deactivate              exitenv
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh

import this

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than \*right\* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

优美胜于丑陋(Python 以编写优美的代码为目标)
明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)
简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)
复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)
扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)
间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)
可读性很重要(优美的代码是可读的)
即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)
不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)
当存在多种可能,不要尝试去猜测而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)
虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido )
做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)
如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)
命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment