导入系统
要使用模块和库,需要先进行导入。
导入系统是相当复杂的,不过你可能已经了解了一些基本知识。这里会介绍一些关于这一子系统的内部机理。
sys模块包含许多关于Python导入系统的信息。首先,当前可导入的模块列表都是通过sys.moudle变量才可以使用的。它是一个字典,其中键(key)是模块名字,对应的值(value)是模块对象。
sys.modules['os']
许多模块是内置的,这些内置的模块在sys.builtin_module_names中列出。内置模块可以根据传入Python构建系统的编译选项的不同而变化。
导入模块时,Python会依赖一个路径列表。这个列表存储在sys.path变量中,并且告诉Python去哪里搜索要加载的模块。可以在代码中修改这个列表,根据需要添加或删除路径,也可以通过编写Python代码直接修改环境变量PYTHONPATH。下面的方法几乎是相等的1。
>>> import sys
>>> sys.path.append('/foo/bar')
$ PYTHONPATH=/foo/bar python
>>> import sys
>>> '/foo/bar' in sys.path
True
在sys.path中顺序很重要,因为需要遍历这个列表来寻找请求的模块。
也可以通过自定义的导入器(importer)对导入机制进行扩展。Hy2正是利用的这种技术告诉Python如何导入其他非标准的.py或者.pyc文件的。
顾名思义,导入钩子机制是由PEP 302(http://www.python.org/dev/pep...)定义的3。它允许扩展标准的导入机制,并对其进行预处理,也可以通过追加一个工厂类到sys.path_hooks来添加自定义的模块查找器(finder)。
模块查找器对象必须有一个返回加载器对象的find_module(fullname, path=None)方法,这个加载器对象必须包含一个负责从源文件中加载模块的load_module(fullname)方法。
为了进一步说明,下面给出了Hy利用自定义的导入器导入.hy而不是.py结尾的源文件的方法,见示例2.1。
示例 Hy模块导入器
class MetaImporter(object):
def find_on_path(self, fullname):
fls = ["%s/__init__.hy", "%s.hy"]
dirpath = "/".join(fullname.split("."))
for pth in sys.path:
pth = os.path.abspath(pth)
for fp in fls:
composed_path = fp % ("%s/%s" % (pth, dirpath))
if os.path.exists(composed_path):
return composed_path
def find_module(self, fullname, path=None):
path = self.find_on_path(fullname)
if path:
return MetaLoader(path)
sys.meta_path.append(MetaImporter())
一旦路径被确定是有效的且指向了一个模块,就会返回一个MetaLoader对象。
Hy模块加载器
class MetaLoader(object):
def __init__(self, path):
self.path = path
def is_package(self, fullname):
dirpath = "/".join(fullname.split("."))
for pth in sys.path:
pth = os.path.abspath(pth)
composed_path = "%s/%s/__init__.hy" % (pth, dirpath)
if os.path.exists(composed_path):
return True
return False
def load_module(self, fullname):
if fullname in sys.modules:
return sys.modules[fullname]
if not self.path:
return
sys.modules[fullname] = None
mod = import_file_to_module(fullname, self.path)
ispkg = self.is_package(fullname)
mod.__file__ = self.path
mod.__loader__ = self
mod.__name__ = fullname
if ispkg:
mod.__path__ = []
mod.__package__ = fullname
else:
mod.__package__ = fullname.rpartition('.')[0]
sys.modules[fullname] = mod
return mod
import_file_to_module读取一个Hy源文件,将其编译成Python代码,并返回一个Python模块对象。
uprefix模块(https://pypi.python.org/pypi/...)是这个功能起作用的另一个好的例子。Python 3.0到3.2并没有像Python 2中用来表示Unicode字符串的u前缀4,这个模块通过在编译前删除字符串的前缀u 来确保在2.x和3.x之间的兼容性。
摘自书中,希望对你有帮助