解释Python入口点?
我看过关于Pylons中的egg入口点和Peak页面的文档,但我还是不太明白。有人能给我解释一下吗?
3 个回答
从抽象的角度来看,入口点是用来创建一个系统范围内的注册表,里面记录了实现特定接口的Python可调用对象。pkg_resources里有一些API,可以查看某个包提供了哪些入口点,也可以用来确定哪些包提供了某个特定的入口点。
入口点的好处在于,它允许一个包使用另一个包中的插件。比如,Ian Bicking的Paste项目就大量使用了入口点。在这种情况下,你可以编写一个包,通过入口点paste.app_factory
来宣传它的WSGI应用工厂。
入口点的另一个用途是列出系统中所有提供某些插件功能的包。TurboGears这个网页框架使用python.templating.engines
入口点来查找已安装和可用的模板库。
入口点(EntryPoints) 是一种持久的、基于文件系统的对象名称注册和基于名称的直接对象导入机制,这个机制是通过setuptools这个包来实现的。
它们将Python对象的名称与自由格式的标识符关联起来。这样,任何其他使用相同Python安装并知道这个标识符的代码,都可以访问与该名称关联的对象,无论这个对象在哪里定义。关联的名称可以是Python模块中存在的任何名称;比如类名、函数名或变量名。入口点机制并不关心这个名称指的是什么,只要它是可以导入的。
举个例子,我们可以用一个函数的名称,以及一个假想的Python模块,完全限定名为'myns.mypkg.mymodule':
def the_function():
"function whose name is 'the_function', in 'mymodule' module"
print "hello from the_function"
入口点是通过在setup.py中声明入口点来注册的。要将the_function注册为名为'my_ep_func'的入口点,可以这样做:
entry_points = {
'my_ep_group_id': [
'my_ep_func = myns.mypkg.mymodule:the_function'
]
},
如例子所示,入口点是分组的;有相应的API可以查找属于某个组的所有入口点(下面有示例)。
在安装一个包时(也就是运行'python setup.py install'),setuptools会解析上述声明。然后,它会将解析的信息写入一个特殊文件中。之后,可以使用pkg_resources API(这是setuptools的一部分)来查找入口点并访问与之关联的对象:
import pkg_resources
named_objects = {}
for ep in pkg_resources.iter_entry_points(group='my_ep_group_id'):
named_objects.update({ep.name: ep.load()})
在这里,setuptools读取了写入特殊文件的入口点信息。它找到了入口点,导入了模块(myns.mypkg.mymodule),并在调用pkg_resources.load()时获取了在那定义的the_function。
调用the_function就变得简单了:
>>> named_objects['my_ep_func']()
hello from the_function
因此,虽然一开始可能有点难以理解,但入口点机制实际上是相当简单易用的。它为可插拔的Python软件开发提供了一个有用的工具。
“入口点”通常指的是一个函数(或者其他可以调用的对象),开发者或者使用你这个Python包的人可能会想用到它。不过,也可以提供一个不可调用的对象作为入口点(正如评论中提到的那样!)。
最常见的入口点类型是 console_scripts
,它指向一个你希望作为命令行工具提供的函数,任何安装你包的人都可以使用。这个内容会放在你的 setup.py
脚本中,像这样:
entry_points={
'console_scripts': [
'cursive = cursive.tools.cmd:cursive_command',
],
},
我刚刚发布了一个叫 cursive.tools
的包,我希望它能提供一个“cursive”命令,用户可以在命令行中运行,比如:
$ cursive --help
usage: cursive ...
实现这个功能的方法是定义一个函数,比如在文件 cursive/tools/cmd.py
中创建一个 cursive_command
函数,内容可能是:
def cursive_command():
args = sys.argv[1:]
if len(args) < 1:
print "usage: ..."
接下来,它应该假设是从命令行调用的,解析用户提供的参数,然后……执行这个命令应该做的事情。
安装 docutils
包可以看到一个很好的入口点使用示例:它会安装大约六个有用的命令,用于将Python文档转换成其他格式。