在這篇文章中,我將解釋關於Python的入口點。大多數人都知道入口點是您在setup.py文件中放入的小片斷,以使您的程序包可做爲命令行上的腳本使用,可是它們可用於更多用途。我將向您展現如何將入口點用做模塊化插件體系結構。若是您想讓其餘人編寫在運行時與現有Python程序包交互或添加功能的Python程序包,這將很是有用。python
!! WARNING: 前方高冷笑話 !!
Snek,Inc.shell
恭喜你!您剛剛被任命爲「 Snek半導體和軟件有限公司」的首席執行官。顯然,您擔任CEO的第一份工做是指示您的研發部門儘快開發出精美的原型。所以,他們開始工做,寫做snek.py:api
ascii_snek = """\ --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` """ def main(): print(ascii_snek) if __name__ == '__main__': main()
他們的原型在公司演示日被展現出來,而且有效!架構
$ python snek.py --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`
不幸的是,客戶對Python並不瞭解(除了snek)。他們但願能夠輕鬆地從命令行(shell)中的任何路徑訪問snek,而沒必要擔憂該Python事情或尋找snek.py。所以,研發部門的負責人通宵工做,並提出了一種打包snek的方法,該方法能夠在安裝後自動建立控制檯腳本。爲Python軟件包建立分發時,須要具備一個setup.py包含軟件包名稱,依賴項等的文件。它也能夠用於註冊入口點,以下所示:app
from setuptools import setup setup( name='snek', entry_points={ 'console_scripts': [ 'snek = snek:main', ], } )
console_scripts 意思是,這是一種特殊的切入點。在安裝軟件包時 setuptools
讀取其內容,"<console script name> = <python object path>"並建立一個適當的腳本。如今,他們正在從源代碼安裝它:ide
$ 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
在備受讚譽的SnekCon會議上的主題演講(門票已提早六個月售罄)中,您登臺演講,並向全世界展現:模塊化
$ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'`
每一個人都喜歡偷偷摸摸。「 Snek半導體和軟件股份有限公司」進行了首次公開募股,市值超過600億美圓。趕時髦的人要求發瘋的版本。您的研發團隊將提供:工具
"""Print an ASCII Snek. Usage: 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()
他們增長了一些幻想。如今,趕時髦的人很高興。ui
$ snek --..,_ _,.--. `'.'. .'`__ o `;__. '.'. .'.'` '---'` ` '.`'--....--'`.' `'--....--'` $ snek --type fancy _,..,,,_ '``````^~"-,_`"-,_ .-~c~-. `~:. ^-. `~~~-.c ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` .:. `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:'
全世界數以百萬計的人正在使用snek。即便收購了Google,「 Snek半導體和軟件有限公司」也沒法跟上對Snek愈來愈多版本的需求增加!專業客戶要求可定製版本的snek!他們想在snek基礎架構之上建立本身的snek。研發更賣力地開始工做。插件
"""Print an ASCII Snek. Usage: 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。每一個snek是在類型名稱下注冊的字符串。該名稱能夠與控制檯腳本一塊兒使用,以動態打印自定義修飾。
特別是,魔術發生在中get_sneks。對的調用會pkg_resources.iter_entry_points('snek_types')
遍歷以名稱註冊的全部入口點"snek_types"。所以,外部包能夠定義稱爲入口點"snek_types"在他們的 setup.py,並snek在運行時將動態加載。
「 Snek Pro解決方案和諮詢服務」的傢伙們知道了有關"snek_types"切入點的事,並已開始研究比您想象中要好得多的snek版本。可愛的snek。他們的cute_snek.py用不多的代碼建立了一個簡單的代碼:
cute_snek = r""" /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~ """
他們在打包 cute_snek,但也須要讓他們snek知道如何找到cute snek。
from setuptools import setup setup( name='cute_snek', entry_points={ 'snek_types': [ 'cute = cute_snek:cute_snek', ], } )
他們以該名稱cute_snek在cute_snek模塊中註冊了該變量cute。如今,他們同時安裝snek和cute_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,它們能夠產生一個可愛的snek,該snek從cute_snek包中動態加載:
$ snek --type cute /^\/^\ _|__| O| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~
您的副總裁研發部有要求。他想中止開發一段時間,而他的工程師則清理snek基礎結構以獲取更好的代碼庫。公開指控稱您在snek交易市場進行內幕交易時挪用了snek的行爲,這讓您太分心了,所以您只好贊成了這樣作。
研發工程師得出的結論是,若是能夠動態加載某些snek,則能夠動態加載全部snek!甚至是內置的snek!他們取消了對現有snek的特殊對待:
--- 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', + ], }, )
如今,您須要從新安裝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| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~
確實,這是一個小小的snek,一個大的snek類型(一樣,您知道如何使用Python入口點)。
注:
英文 snek有不少含義,注意辨別:
snek
[snek]
WHAT DOES SNEK MEAN?
Snek is internet-speak for snake. Sneks became the subject of cute, absurdist memes depicting the reptiles' inner monologue ... similar to doge.
Snek appears as what seems to be genuine misspelling in the titles of several YouTube videos between 2009 and 2011. One, uploaded under the title 「Baby.snek (1).3gp,」 shows a baby playing with a King Cobra snake. Or, is it a snake playing with a baby? Either way, we don’t recommend it.
By 2012, snek was being used as an intentional misspelling in memes, part of a larger culture of deliberately silly-stupid misspellings and bad grammar seen in LOLcat (e.g., I can haz moar?), doge (such wow!), and DoggoLingo (smol) memes. One from that time showed a woman apparently trying to keep a huge snake from escaping. The captions, meant to be her inner monologue, ask the snek to 「stahp,」 or stop.