https://amir.rachum.com/blog/2017/07/28/python-entry-points/
随心所欲翻译版本.侵删.
这篇文章将会聊聊python代码中的入口点.很多人可能知道,入口点一般会放在文件中,经过打包后可以作为命令行使用,不过很少有人会去用它.接下来,我将会介绍如何使用入口点生成python包,之后就可以让别人在代码中或者命令行下使用.
安装过python包的都知道使用,就是定义了你自己开发的包的相关信息,然后可以打包上传到python的包管理中心供别人下载.而入口点可以让包作为命令行工具使用.
Snek,Inc.
恭喜你!你刚刚被任命为”snek半导体和软件公司”的CEO,作为CEO,你的第一个工作是让员工开发出snek的原型系统,很快,工程师就做出来了,它是一个python脚本,:
ascii_snek ="""\ --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`"""
defmain(): print(ascii_snek)
if__name__ =='__main__': main()
在公司产品发布的那一天,你演示了这个原型系统,运行很顺利:
$ python snek.py --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`
SaaS—Snek as a Service
不幸的是,用户不会使用python,他们只想在电脑的命名行下直接使用Snek的服务,于是工程师们加班加点作出了下一个版本,让snek在安装时自动生成控制台脚本,这样就可以在命令行下运行了.他们是怎么做的?只需要在 脚本中包含包名,依赖等信息,像下面这样:
下面的代码就是指定了应该从snek脚本的main函数开始执行.
fromsetuptoolsimportsetupsetup( name='snek', entry_points={
'console_scripts': [
'snek = snek:main', ], })
工程师说,控制台脚本就是特殊的入口点,在你的包被别人安装时,读取其中的内容并生成某些脚本文件.现在,让我们从源代码中安装(当然你可以发布为python库,让别人使用pip下载安装):
$ python setup.py developrunning developrunning egg_infowriting snek.egg-info\PKG-INFOwriting dependency_links to snek.egg-info\dependency_links.txtwriting entry points to snek.egg-info\entry_points.txtwriting top-level names to snek.egg-info\top_level.txtreading manifest file'snek.egg-info\SOURCES.txt'writing manifest file'snek.egg-info\SOURCES.txt'running build_extCreating c:\program files (x86)\py36-32\lib\site-packages\snek.egg-link (link to .)snek0.0.is already the active versionineasy-install.pthInstalling snek-script.py script to C:\Program Files (x86)\Py36-32\ScriptsInstalling snek.exe script to C:\Program Files (x86)\Py36-32\ScriptsInstalling snek.exe.manifest script to C:\Program Files (x86)\Py36-32\ScriptsInstalled c:\users\rachum\notebooksProcessing dependenciesforsnek==0.0.Finished processing dependenciesforsnek==0.0.
在公司的年度产品会上,你展示了这个amazing的产品:
$ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`
Snek for Everyone
没有人不喜欢Snek,公司的IPO超过了60亿美元.有些高级用户希望为他们量身定制高级的版本.工程师又加班加点做了出来:
"""Print an ASCII Snek.Usage: snek [--type=TYPE]"""
importdocoptnormal_snek ="""\ --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`"""
fancy_snek ="""\ _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:' ':..___.:'"""
defget_sneks():
return{
'normal': normal_snek,
'fancy': fancy_snek, }
defmain(): args = docopt.docopt(__doc__) snek_type = args['--type']or'normal'print(get_sneks()[snek_type])
if__name__ =='__main__': main()
他们加了一个豪华版的Snek,这让高级用户特别开心.
$ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`$ snek --type fancy _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .'.: :' _.-~^~-. `. `..'.: `.' : .'_:' .-'`. :. .: .'`. : ; : `-'.:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,'': '.__.` :' ~--..--'':. .:'':..___.:'
Snek International Community
全球数百万人都在使用snek,人们对snek不同版本的需求越来越高,而且一些snek的专业用户(程序员)要求snek可以定制,他们想开发自己的snek版本.
"""Print an ASCII Snek.Usage: snek [--type=TYPE]"""
importdocopt
importpkg_resourcesnormal_snek ="""\ --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`"""
fancy_snek ="""\ _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:' ':..___.:'"""
defget_sneks(): sneks = {
'normal': normal_snek,
'fancy': fancy_snek, }
forentry_pointinpkg_resources.iter_entry_points('snek_types'): sneks[entry_point.name] = entry_point.load()
returnsneks
defmain(): args = docopt.docopt(__doc__) snek_type = args['--type']or'normal'print(get_sneks()[snek_type])
if__name__ =='__main__': main()
他们增加了snek的基础架构,当snek运行时,使用被称作的入口点注册其他类型的snek,这样就能动态的在控制台输出不同的snek版本.
具体来说,中的遍历所有注册到入口点的snek名,然后加入snek版本中.于是,开发者们加入了一个可爱版本的snek,命名为:
cute_snek =r""" /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~"""
如何找到这个可爱版本的snek呢?像下面这样定义:
代码中指定了从脚本寻找cute_snek.
fromsetuptoolsimportsetupsetup( name='cute_snek', entry_points={
'snek_types': [
'cute = cute_snek:cute_snek', ], })
然后像之前一样打包:
$cdcute_snek && python setup.py developrunning developrunning egg_infowriting cute_snek.egg-info\PKG-INFOwriting dependency_links to cute_snek.egg-info\dependency_links.txtwriting entry points to cute_snek.egg-info\entry_points.txtwriting top-level names to cute_snek.egg-info\top_level.txtreading manifest file'cute_snek.egg-info\SOURCES.txt'writing manifest file'cute_snek.egg-info\SOURCES.txt'running build_extCreating c:\program files (x86)\py36-32\lib\site-packages\cute-snek.egg-link (link to .)cute-snek0.0.is already the active versionineasy-install.pthInstalled c:\users\rachum\cute_snekProcessing dependenciesforcute-snek==0.0.Finished processing dependenciesforcute-snek==0.0.
现在我们就能在命令行下成功的运行这个可爱版本的snek,这是从中动态加载的:
$ snek --type cute /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~
既然cute_snek可以动态的加载,那么所有类型的snek应该都可以动态加载,于是工程师们又修改了代码:
所有的snek都从中加载.
fromsetuptoolsimportsetupsetup( name='cute_snek', entry_points={
'snek_types': [
'cute = cute_snek:cute_snek',
'normal = snek:normal_snek',
'fancy = snek:fancy_snek', ], })
# 同时修改之前文件中的get_sneks()函数:
defget_sneks():
#sneks = {# 'normal': normal_snek,# 'fancy': fancy_snek,#}# 将snek修改为空字典snek = {}
forentry_pointinpkg_resources.iter_entry_points('snek_types'): sneks[entry_point.name] = entry_point.load()
returnsneks
现在重新打包snek:
$ python setup.py developrunning developrunning egg_infowriting snek.egg-info\PKG-INFOwriting dependency_links to snek.egg-info\dependency_links.txtwriting entry points to snek.egg-info\entry_points.txtwriting top-level names to snek.egg-info\top_level.txtreading manifest file'snek.egg-info\SOURCES.txt'writing manifest file'snek.egg-info\SOURCES.txt'running build_extCreating c:\program files (x86)\py36-32\lib\site-packages\snek.egg-link (link to .)snek0.0.is already the active versionineasy-install.pthInstalling snek-script.py script to C:\Program Files (x86)\Py36-32\ScriptsInstalling snek.exe script to C:\Program Files (x86)\Py36-32\ScriptsInstalling snek.exe.manifest script to C:\Program Files (x86)\Py36-32\ScriptsInstalled c:\users\rachum\notebooksProcessing dependenciesforsnek==0.0.Finished processing dependenciesforsnek==0.0.
大功告成!!!
$ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`$ snek --type fancy _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .'.: :' _.-~^~-. `. `..'.: `.' : .'_:' .-'`. :. .: .'`. : ; : `-'.:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,'': '.__.` :' ~--..--'':. .:'':..___.:'$ snek --type cute /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~
到此为止,你应该大概知道了如何使用python中的入口点了吧.
领取专属 10元无门槛券
私享最新 技术干货