python模块与包加载机制
模块的搜索路径:
When a module named spam is imported, the interpreter searches for a file named spam.py in the current directory, and then in the list of directories specified by the environment variable PYTHONPATH. This has the same syntax as the shell variable PATH, that is, a list of directory names. When PYTHONPATH is not set, or when the file is not found there, the search continues in an installation-dependent default path; on Unix, this is usually .:/usr/local/lib/python.
导入一个叫 spam 的模块时,解释器先在当前目录中搜索名为 spam.py 的文件,然后在环境变量 PYTHONPATH 表示的目录列表中搜索,。如果 PYTHONPATH没有设置,或者文件没有找到,接下来搜索安装目录,在UNIX中,通常是 .:/usr/local/lib/python。
当前目录-》PYTHONPATH->python安装默认目录
Actually, modules are searched in the list of directories given by the variable sys.path which is initialized from the directory containing the input script (or the current directory), PYTHONPATH and the installation-dependent default. This allows Python programs that know what they're doing to modify or replace the module search path. Note that because the directory containing the script being run is on the search path, it is important that the script not have the same name as a standard module, or Python will attempt to load the script as a module when that module is imported. This will generally be an error. See section 6.2, ``Standard Modules,'' for more information.
实际上,解释器由 sys.path 变量指定的路径目录搜索模块,该变量初始化时默认包含了输入脚本(或者当前目录), PYTHONPATH 和安装目录。这样就允许Python程序(原文如此,programs;我猜想应该是“programer”,程序员--译者)了解如何修改或替换模块搜索目录。需要注意的是由于这些目录中包含有搜索路径中运行的脚本,所以这些脚本不应该和标准模块重名,否则在导入模块时Python会尝试把这些脚本当作模块来加载。这通常会引发一个错误。请参见 6.2节“标准模块”以了解更多的信息。
转自:Python手册Python Tutorial
除了使用import sys这样的方式加载module之外,
还可以使用:
import sys
sys.path.append('f:\\python\works')
sys.path.insert(0,'f:\\c‘)
1)关于module
通常模块为一个文件,直接使用import来导入就好了。
可以作为module的文件类型有".py"、".pyo"、".pyc"、".pyd"、".so"、".dll"。
2)关于package
通常包总是一个目录,可以使用import导入包,
或者from + import来导入包中的部分模块。
包目录下为首的一个文件便是 __init__.py。
然后是一些模块文件和子目录,假如子目录中也有 __init__.py 那么它就是这个包的子包了。
使用import spam 语句就可以将这个文件(spam)作为模块导入。
默认的检索路径为执行python的当前路径和sys.path路径
系统在导入模块时,要做以下三件事:
1. 为源代码文件中定义的对象创建一个命名空间,通过这个命名空间可以访问到模块中定义的函数及变量。
2. 在新创建的命名空间里执行源代码文件。
3. 创建一个名为源代码文件的对象,该对象引用模块的命名空间,这样就可以通过这个对象访问模块中的函数及变量,如:
import spam # 导入并运行模块 spam
print spam.a # 访问模块 spam 的属性
spam.foo()
c = spam.bar()
...
用逗号分割模块名称就可以同时导入多个模块:
import socket, os, regex模块导入时可以使用 as 关键字来改变模块的引用对象名字:
import os as system
import socket as net, thread as threads
system.chdir("..")
net.gethostname()
使用from语句可以将模块中的对象直接导入到当前的名字空间. from语句不创建一个到模块名字空间的引用对象,而是把被导入模块的一个或多个对象直接放入当前的名字空间:
from socket import gethostname
# 将gethostname放如当前名字空间
print gethostname() # 直接调用
socket.gethostname() # 引发异常NameError: socket
from语句支持逗号分割的对象,也可以使用星号(*)代表模块中除下划线开头的所有对象:
from socket import gethostname, socket
from socket import * # 载入所有对象到当前名字空间
import 语句可以在程序的任何位置使用,你可以在程序中多次导入同一个模块,但模块中的代码*仅仅*在该模块被首次导入时执行。后面的import语句只是简单的创建一个到模块名字空间的引用而已。sys.modules字典中保存着所有被导入模块的模块名到模块对象的映射。这个字典用来决定是否需要使用import语句来导入一个模块的最新拷贝.
from module import * 语句只能用于一个模块的最顶层.*特别注意*:由于存在作用域冲突,不允许在函数中使用from 语句。
每个模块都拥有 __name__ 属性,它是一个内容为模块名字的字符串。最顶层的模块名称是 __main__ .命令行或是交互模式下程序都运行在__main__ 模块内部. 利用__name__属性,我们可以让同一个程序在不同的场合(单独执行或被导入)具有不同的行为,象下面这样做:
# 检查是单独执行还是被导入
if __name__ == '__main__':
# Yes
statements
else:
# No (可能被作为模块导入)
statements
模块搜索路径
导入模块时,解释器会搜索sys.path列表,这个列表中保存着一系列目录。一个典型的sys.path 列表的值:
Linux:
['', '/usr/local/lib/python2.0',
'/usr/local/lib/python2.0/plat-sunos5',
'/usr/local/lib/python2.0/lib-tk',
'/usr/local/lib/python2.0/lib-dynload',
'/usr/local/lib/python2.0/site-packages']
Windows:
['', 'C:\\WINDOWS\\system32\\python24.zip', 'C:\\Documents and Settings\\weizhong', 'C:\\Python24\\DLLs', 'C:\\Python24\\lib', 'C:\\Python24\\lib\\plat-win', 'C:\\Python24\\lib\\lib-tk', 'C:\\Python24\\Lib\\site-packages\\pythonwin', 'C:\\Python24', 'C:\\Python24\\lib\\site-packages', 'C:\\Python24\\lib\\site-packages\\win32', 'C:\\Python24\\lib\\site-packages\\win32\\lib', 'C:\\Python24\\lib\\site-packages\\wx-2.6-msw-unicode']
空字符串 代表当前目录. 要加入新的搜索路径,只需要将这个路径加入到这个列表.
二包
多个关系密切的模块应该组织成一个包,以便于维护和使用。这项技术能有效避免名字空间冲突。创建一个名字为包名字的文件夹并在该文件夹下创建一个__init__.py 文件就定义了一个包。你可以根据需要在该文件夹下存放资源文件、已编译扩展及子包。举例来说,一个包可能有以下结构:
Graphics/
__init__.py
Primitive/
__init__.py
lines.py
fill.py
text.py
...
Graph2d/
__init__.py
plot2d.py
...
Graph3d/
__init__.py
plot3d.py
...
Formats/
__init__.py
gif.py
png.py
tiff.py
jpeg.py
import语句使用以下几种方式导入包中的模块:
* import Graphics.Primitive.fill 导入模块Graphics.Primitive.fill,只能以全名访问模块属性,例如Graphics.Primitive.fill.floodfill(img,x,y,color).
* from Graphics.Primitive import fill 导入模块fill ,只能以 fill.属性名这种方式访问模块属性,例如fill.floodfill(img,x,y,color).
* from Graphics.Primitive.fill import floodfill 导入模块fill ,并将函数floodfill放入当前名称空间,直接访问被导入的属性,例如 floodfill(img,x,y,color).
无论一个包的哪个部分被导入, 在文件__init__.py中的代码都会运行.这个文件的内容允许为空,不过通常情况下它用来存放包的初始化代码。导入过程遇到的所有 __init__.py文件都被运行.因此 import Graphics.Primitive.fill 语句会顺序运行 Graphics 和 Primitive 文件夹下的__init__.py文件.
下边这个语句具有歧义:
from Graphics.Primitive import *
这个语句的原意图是想将Graphics.Primitive包下的所有模块导入到当前的名称空间.然而,由于不同平台间文件名规则不同(比如大小写敏感问题), Python不能正确判定哪些模块要被导入.这个语句只会顺序运行 Graphics 和Primitive 文件夹下的__init__.py文件. 要解决这个问题,应该在Primitive文件夹下面的__init__.py中定义一个名字all的列表,例如:
# Graphics/Primitive/__init__.py
__all__ = ["lines","text","fill",...]
这样,上边的语句就可以导入列表中所有模块.
下面这个语句只会执行Graphics目录下的__init__.py文件,而不会导入任何模块:
import Graphics
Graphics.Primitive.fill.floodfill(img,x,y,color) # 失败!
不过既然 import Graphics 语句会运行 Graphics 目录下的 __init__..py文件,我们就可以采取下面的手段来解决这个问题:
# Graphics/__init__.py
import Primitive, Graph2d, Graph3d
# Graphics/Primitive/__init__.py
import lines, fill, text, ...
这样import Graphics语句就可以导入所有的子模块(只能用全名来访问这些模块的属性).
refer to:http://blog.csdn.net/appleheshuang/article/details/7602499
python模块与包加载机制的更多相关文章
- Python模块的动态加载机制
Python在运行环境初始化中,就将sys module加载到了内存中, 实际上,Python是将一大批的module加载到了内存中.但是为了使local名字空间能够达到最干净的效果,Python并没 ...
- 基于python的opcode优化和模块按需加载机制研究(学习与个人思路)(原创)
基于python的opcode优化和模块按需加载机制研究(学习与思考) 姓名:XXX 学校信息:XXX 主用编程语言:python3.5 个人技术博客:http://www.cnblogs.com/M ...
- node.js的包加载机制
加载一个模块 require('moduleName'); 现在核心模块中加载,如果核心模块中没有,那么就去node_modules目录下去找,核心模块的优先级最高. 如果加载模块式省略了文件的后缀名 ...
- nodejs 模块以及加载机制,主要讨论找不到模块的问题
最主要的一个思想,加载模块无非就是找到模块在哪,只要清楚了模块的位置以及模块加载的逻辑那么找不到模块的问题就迎刃而解了.本文只是综合了自己所学的知识点进行总结,难免出现理解错误的地方,请见谅. nod ...
- Skywalking-13:Skywalking模块加载机制
模块加载机制 基本概述 Module 是 Skywalking 在 OAP 提供的一种管理功能特性的机制.通过 Module 机制,可以方便的定义模块,并且可以提供多种实现,在配置文件中任意选择实现. ...
- 【前端】CommonJS的模块加载机制
CommonJS的模块加载机制 CommonJS模块的加载机制是,输入的是被输出的值的拷贝.也就是说,一旦输出一个值,模块内部的变化就影响不到这个值. 例如: // lib.js var counte ...
- Dojo初探之1:AMD规范,编写符合AMD规范(异步模块加载机制)的模块化JS(其中dojo采用1.11.2版本)
一.AMD规范探索 1.AMD规范(即异步模块加载机制) 我们在接触js的时候,一般都是通过各种function来定义一些方法,让它们帮我们做一些事情,一个js可以包含很多个js,而这些functio ...
- webpack4下import()模块按需加载,打包按需切割模块,减少包体积,加快首页请求速度
一:背景 因为项目功能越加越多,打包后的体积越来越大,导致首页展示的时候速度比较慢,因为要等压缩的js的包加载完毕. 首页展示的时候只需要对应的js,并不需要全部的js模块,所以这里就可以用按需加载, ...
- nodejs(13)模块加载机制
模块加载机制 优先从缓存中加载 当一个模块初次被 require 的时候,会执行模块中的代码,当第二次加载相同模块的时候,会优先从缓存中查找,看有没有这样的一个模块! 好处:提高模块的加载速度:不需要 ...
随机推荐
- Google Map API v2 步步为营(一) ----- 初见地图
官方文档:https://developers.google.com/maps/documentation/android/start?hl=zh-CN 先谷歌后百度.使用google的api基本上按 ...
- centos emacs安装
wget http://mirrors.ustc.edu.cn/gnu/emacs/emacs-24.5.tar.gz tar zxvf emacs-24.5.tar.gz cd emacs-24.5 ...
- CoreAnimation2-视觉效果和变换
圆角 圆角矩形是iOS的一个标志性审美特性.这在iOS的每一个地方都得到了体现,不论是主屏幕图标,还是警告弹框,甚至是文本框.按照这流行程度,你可能会认为一定有不借助Photoshop就能轻易创建圆角 ...
- 检查.gitignore语法
每次配置git的时候,要写gitignore文件,你知道你的.gitignore匹配那些文件吗? 看看.gitignore放过了哪些文件: git ls-files -ocm --exclude-st ...
- Java程序实现导出Excel,支持IE低版本
来博客园两年多了,最近才开通了微博,因为懒所以也一直没有写东西,今天想整理一下自己前段时间遇到的一个导出的问题. 因为项目的需求,要做一部分导出功能.开始的时候用的公司的导出,但是很奇怪有部分模块导出 ...
- ScheduleThreadPoolExecutor源码分析
ScheduleThreadPoolExecutor源码分析(一) Java中ScheduleThreadPoolExecutor主要用于执行延迟任务或者按照一定的频率执行任务.其中scheduleA ...
- 回退符\b
回退符\b #include <stdio.h> int main(){ printf("hello\b"); getchar(); getchar(); ; } 实验 ...
- c++builder调用vc的dll
$bcb/bin目录中有个implib.exe 把你的vc.dll和implib.exe复制到c盘根目录下 运行cmd 进入c盘根目录执行 c:\implib -a cb.lib vc.dll 会生成 ...
- gridview列前加复选框需要注意的一点
前言 获取gridview每一列前面的复选框,然后获取选中的这一行的id.aspx页面,我不喜欢用这个,有的公司用自己封装的,基本上都是用封装的,这是我知道的.也有用Repeater的.可能是因为gr ...
- C# 启动和结束一个线程
在程序执行中会遇到启动本软件的exe问,或者启用其它的exe文件,已达到执行某些操作的作用.下面是两种最常见的启动exe文件. 1.调用系统dll使用其提供的方法. 引用的dll, [DllImpor ...