Python入口点

许多人认为入口点是setup.py中的说明,这些说明使程序包可从命令行运行。 通常这是正确的,但是入口点的功能不限于此。

下面,我将展示如何为一个程序包实现一个插件系统,以便其他人可以与之交互或例如动态地扩展其功能。



注意 :下文中具体幽默。

LLC“蛇”


恭喜你! 您刚刚被任命为​​Snake LLC的负责人。 这是一个非常负责任的职位,您不能面对尘土,这意味着您需要尽快指示开发部门开始创建产品原型。 因此,公司的最佳人才开始在snek.py上工作:

ascii_snek = """\ --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` """ def main(): print(ascii_snek) if __name__ == '__main__': main() 

不久之后,在股东大会上,您自豪地展示了最初的结果!

 $ python snek.py --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` 

蛇即服务


不幸的是,普通消费者尚未掌握Python,并且希望从控制台运行该程序而不考虑解释器或位置snek.py。 好吧,我们最好的专家就是能够打包脚本以便在安装过程中自动创建控制台命令的最好的专家。

要创建可重新分发的程序包,我们需要setup.py文件 ,其中包含有关依赖项,许可证等的信息。 另外,您可以在其中指定入口点:

 from setuptools import setup setup( name='snek', entry_points={ 'console_scripts': [ 'snek = snek:main', ], } ) 

专家解释说, console_scripts是一个特殊的入口点。 setuptools将其元素读取为“ <控制台脚本> = <Python对象的路径>” ,在安装软件包时为每个元素创建一个控制台实用程序。

现在,让我们从源代码安装脚本:

 $ python setup.py develop running develop running egg_info writing snek.egg-info\PKG-INFO writing dependency_links to snek.egg-info\dependency_links.txt writing entry points to snek.egg-info\entry_points.txt writing top-level names to snek.egg-info\top_level.txt reading manifest file 'snek.egg-info\SOURCES.txt' writing manifest file 'snek.egg-info\SOURCES.txt' running build_ext Creating c:\program files (x86)\py36-32\lib\site-packages\snek.egg-link (link to .) snek 0.0.0 is already the active version in easy-install.pth Installing snek-script.py script to C:\Program Files (x86)\Py36-32\Scripts Installing snek.exe script to C:\Program Files (x86)\Py36-32\Scripts Installing snek.exe.manifest script to C:\Program Files (x86)\Py36-32\Scripts Installed c:\users\rachum\notebooks Processing dependencies for snek==0.0.0 Finished processing dependencies for snek==0.0.0 

在专门讨论年度业绩的会议上,您讲话并演示了最新的进展:

 $ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` 

每个房子里都有一条蛇


蛇征服了世界。 该公司进行了首次公开募股,市值达到创纪录的600亿美元。 赶时髦的人需要一条新的,时尚的,时髦的和年轻的蛇。 如果有需求,就会有一个报价:

 """ ASCII . : snek [--type=TYPE] """ import docopt normal_snek = """\ --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` """ fancy_snek = """\ _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:' ':..___.:' """ def get_sneks(): return { 'normal': normal_snek, 'fancy': fancy_snek, } def main(): args = docopt.docopt(__doc__) snek_type = args['--type'] or 'normal' print(get_sneks()[snek_type]) if __name__ == '__main__': main() 

赶时髦的人很激动:

 $ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` $ snek --type fancy _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:' ':..___.:' 

跨国蛇


数百万人无法想象没有蛇的日子。 即使在Google接管之后,Zmeika的资源仍不足以满足全球用户的需求。 似乎是时候让人们有机会根据我们的基础设施创建自己的蛇了。

 """ ASCII . : snek [--type=TYPE] """ import docopt import pkg_resources normal_snek = """\ --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` """ fancy_snek = """\ _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:' ':..___.:' """ def get_sneks(): sneks = { 'normal': normal_snek, 'fancy': fancy_snek, } for entry_point in pkg_resources.iter_entry_points('snek_types'): sneks[entry_point.name] = entry_point.load() return sneks def main(): args = docopt.docopt(__doc__) snek_type = args['--type'] or 'normal' print(get_sneks()[snek_type]) if __name__ == '__main__': main() 

现在,每次启动snek时 ,它都会使用snek_types入口搜索在系统中注册的其他蛇。 每个此类蛇都以其类型的名称注册,这使您可以根据控制台的参数选择所需的蛇。

最重要的事情发生在get_sneks内部。 调用pkg_resources.iter_entry_points('snek_types')可使您遍历任何以“ snek_types”名称注册的入口点。 因此,任何第三方包都将能够在setup.py中创建一个入口点“ snek_types” ,以与我们的脚本一起加载。

我们与Snake Solutions LLC的同事讨论了snek_types ,他们立即开始创造他们梦the 以求的蛇。 这就是他们的cute_snek.py包的产生方式:

 cute_snek = r""" /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~ """ 

这是他们实现setup.py的方式,以便我们的小偷可以加载蛇:

 from setuptools import setup setup( name='cute_snek', entry_points={ 'snek_types': [ 'cute = cute_snek:cute_snek', ], } ) 

他们在cute_snek模块中以cute这个名字注册了cute_snek变量。 接下来,他们安装snekcute_snek软件包

 $ cd cute_snek && python setup.py develop running develop running egg_info writing cute_snek.egg-info\PKG-INFO writing dependency_links to cute_snek.egg-info\dependency_links.txt writing entry points to cute_snek.egg-info\entry_points.txt writing top-level names to cute_snek.egg-info\top_level.txt reading manifest file 'cute_snek.egg-info\SOURCES.txt' writing manifest file 'cute_snek.egg-info\SOURCES.txt' running build_ext Creating c:\program files (x86)\py36-32\lib\site-packages\cute-snek.egg-link (link to .) cute-snek 0.0.0 is already the active version in easy-install.pth Installed c:\users\rachum\cute_snek Processing dependencies for cute-snek==0.0.0 Finished processing dependencies for cute-snek==0.0.0 

现在,通过运行snek ,他们可以通过在入口点动态加载它来使它们的蛇脱离cute_snek包:

 $ snek --type cute /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~ 

蛇2.0


尽管最高管理层的所有注意力都集中在与税务检查机构和反垄断服务部门进行拆卸上,但是开发部门最终可以找到一些时间来重构代码。

首席系统架构师意识到,如果可以将第三方蛇作为插件下载,那么也可以下载内置蛇。

我们删除了对内置蛇的特殊处理:

 --- a/snek.py +++ b/snek.py @@ -31,10 +31,7 @@ fancy_snek = """\ """ def get_sneks(): - sneks = { - 'normal': normal_snek, - 'fancy': fancy_snek, - } + sneks = {} for entry_point in pkg_resources.iter_entry_points('snek_types'): sneks[entry_point.name] = entry_point.load() return sneks 

作为回报,我们将为其注册通用入口点:

 --- a/setup.py +++ b/setup.py @@ -6,5 +6,9 @@ setup( 'console_scripts': [ 'snek = snek:main', ], + 'snek_types': [ + 'normal = snek:normal_snek', + 'fancy = snek:fancy_snek', + ], }, ) 

重新安装修改后的蛇:

 $ python setup.py develop running develop running egg_info writing snek.egg-info\PKG-INFO writing dependency_links to snek.egg-info\dependency_links.txt writing entry points to snek.egg-info\entry_points.txt writing top-level names to snek.egg-info\top_level.txt reading manifest file 'snek.egg-info\SOURCES.txt' writing manifest file 'snek.egg-info\SOURCES.txt' running build_ext Creating c:\program files (x86)\py36-32\lib\site-packages\snek.egg-link (link to .) snek 0.0.0 is already the active version in easy-install.pth Installing snek-script.py script to C:\Program Files (x86)\Py36-32\Scripts Installing snek.exe script to C:\Program Files (x86)\Py36-32\Scripts Installing snek.exe.manifest script to C:\Program Files (x86)\Py36-32\Scripts Installed c:\users\rachum\notebooks Processing dependencies for snek==0.0.0 Finished processing dependencies for snek==0.0.0 

检查结果:

 $ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` $ snek --type fancy _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:' ':..___.:' $ snek --type cute /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~ 



仅此而已。 现在您知道了如何在Python中使用入口点!

Source: https://habr.com/ru/post/zh-CN479570/


All Articles