注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

蜻蜓点水 举重若轻

君子终日乾乾

 
 
 

日志

 
 

import 初探之二 —— __import__() 、reload() 及受限脚本

2006-10-30 17:35:20|  分类: Python |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
逐渐起飞


放下尼龙弦吉他,点下鼠标左键,退出 GP3 —— 即使是老版本,我还是比不上它的弹奏速度。但庆幸的是我还能勉强地跟上 Python 的节奏 —— 巨蟒的飞行速度。


import 自古以来就没有发生过什么大的变化,只有在一次版本更替中引入了 as 关键词。这种变化温和到以至于我们常常会忘记 as 其实是在后来才加进来的,这正叫做随风潜入夜润物细无声啊。

import string as string1, string as string2
from string import strip as strip1, strip as strip2



__import__()


嗯,import 总会去调这个玩艺的。也就是说你可以重载这个函数,让 Python 在导入好东东之前先做出许多好玩的事情来:

old_imp = __buildins__.__import__
def
new_imp(module_name, globals=None, locals=None, fromlist=[]):
print module_name
return old_imp(module_name, globals, locals, fromlist)



__buildins__.__import__ = new_imp

__import__() 的完全调用形式是 __import__(name, globals, locals, fromlist),name 即模块名、其后是全局和局部变量,最后是在模块中要导入的列表。比如:

__import__('string', globals(), locals(), ['join', 'split'])


当然,通常你可能会判断一下该模块是否已经导入过了。或者把你讨厌的东西拒之门外。



reload()


这个听起来有点像是我的那个金属酒瓶。我与它在岗顶的那家小店铺之中一见钟情,结果花去我 140 ¥——当然威士忌要更贵一点。


reload 函数的意思就是旧瓶装新酒了。比如我们已经 import something 了,但是外面的 something.py 模块文件的内容突然改变、更新了,如果要享受新的 somethin.py 的好处,我们就需要 reload 一下了。


据说 reload 通常和一种神秘的仪式有关。差不多类似于这样吧:

""" maillist.py
向远程 Mail 服务器查询是否有新邮件。
服务器返回一个 Python 模块文件,把结果封装在 show() 函数中。
"""

def
download_netobj(url, module_name):
import urllib
web_file = urllib.urlopen(url)
buff = web_file.read()
web_file.close()
module_file = open(module_name + '.py', 'w')
module_file.write(buff)
module_file.close()

#查询邮件

download_netobj(
'http://http://blog.czug.org/eishn/mail_list.cgi?user=eishn&pass=6star',
'mail_list')

import mail_list
mail_list.show()

#好的,过一会儿再查询吧。

import time
time.sleep(100)

#再次查询

download_netobj(
'http://http://blog.czug.org/eishn/mail_list.cgi?user=eishn&pass=6star',
'mail_list'
)

reload(mail_list)
mail_list.main()

reload() 通常对应的就是这种玩法。因为模块之所以会更新,大多数的情况是由于——模块它自网上来。除了邮件服务,其他的玩法大同小异。自从对“程序混着数据传来传去”不再恶心之后,沈崴开始乐衷于此道,并开始自觉地传道。


这就像是魔兽的地图,既有静态数据,又有许多 道具和人物。这些道具和人物的控制程序同时被封装在假装是地图的那个文件里。这样那些游戏们就可以动态的随着地图的不同改变更多的行为了,比如添加更多地 图特有的变态道具。


reload() 和 __import__() 一样是可以重载的。



什么是 __builtins__

__builtins__ 是一个名字空间,是系统自动生成的,其中的内容是直接可调用的。我们可以尝试着导入一个叫做 __builtin__ 的模块,如果发现模块 __builtin__ 与名字空间 __builtins__ 中的内容无异,那么我们正运行在一个无限制的 Python 执行环境下。



定制脚本执行环境


当然,重定义 __import__() 有着另一层深刻的含义 —— 如果你想定制一个自己的脚本执行环境的话。这让我们想起 Zope 中的 "Python Script" 执行环境,只能使用 Zope 所允许的模块,这相当酷。

简单的做法,覆盖掉脚本的 __builtins__.__import__ 函数,使之只能导入限定的模块。

修改脚本的 __builtins__。当然我们已经知道了,如果想给它完全的执行环境可以把 module __builtin__ 的内容赋给脚本的 __builtins__ 名字空间 —— 其实系统总是默认地做了这件事情了。

好了,下面是一个订制脚本执行环境的简单例子:

execfile('script.py', {'__builtins__': {'__import__':lambda name, globals, locals, fromlist:None} } )


现在,script.py 这个脚本所能做的事情相当,相当有限了。



imp 模块


imp 模块是专业的导入功能定制模块,而且它给人一较为底层的映象。在网上可以找到一种叫做 knee.py 的脚本,它讲了很多。


但是我从来没有想过来使用这个模块,因为 imputil 工具模块要更为亲和一点。使用 imp 或者 imputil 模块可以让你的程序于“无法在本地找到某一个模块”时自动地区网上下载下来并导入,这显得比上面 reload 一节中的那个邮件程序更为聪明了。



欲练神功,挥刀自宫


在开始关于 import 的下面两辑(之三、之四)之前,我想最好还是忘了本辑和第一集的内容吧,尽管他们是大厦的基础,但是与新时代的 import 玩法似乎已经有些格格不入了。

  评论这张
 
阅读(2265)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017