Python入口點介紹

2021-04-24 03:00:08

在這篇文章中,我將解釋關於Python的入口點。大多數人都知道入口點是您在setup.py檔案中放入的小片段,以使您的程式包可作為命令列上的指令碼使用,但是它們可用於更多用途。我將向您展示如何將入口點用作模組化外掛體系結構。如果您想讓其他人編寫在執行時與現有Python程式包互動或新增功能的Python程式包,這將非常有用。

!! WARNING: 前方高冷笑話 !!
Snek,Inc.

恭喜你!您剛剛被任命為​​「 Snek半導體和軟體有限公司」的執行長。顯然,您擔任CEO的第一份工作是指示您的研發部門儘快開發出精美的原型。因此,他們開始工作,寫作snek.py:

ascii_snek = """\
    --..,_                     _,.--.
       `'.'.                .'`__ o  `;__.
          '.'.            .'.'`  '---'`  `
            '.`'--....--'`.'
              `'--....--'`
"""

def main():
    print(ascii_snek)
    
if __name__ == '__main__':
    main()

他們的原型在公司演示日被展示出來,並且有效!

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

SaaS-Snek即服務

不幸的是,客戶對Python並不瞭解(除了snek)。他們希望可以輕鬆地從命令列(shell)中的任何路徑存取snek,而不必擔心該Python事情或尋找snek.py。因此,研發部門的負責人通宵工作,並提出了一種打包snek的方法,該方法可以在安裝後自動建立控制檯指令碼。為Python軟體包建立分發時,需要具有一個setup.py包含軟體包名稱,依賴項等的檔案。它也可以用於註冊入口點,如下所示:

from setuptools import setup

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

console_scripts 意思是,這是一種特殊的切入點。在安裝軟體包時 setuptools 讀取其內容,"<console script name> = <python object path>"並建立一個適當的指令碼。現在,他們正在從原始碼安裝它:

$ 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()

他們增加了一些幻想。現在,趕時髦的人很高興。

$ 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!他們取消了對現有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.

see: https://www.dictionary.com/e/...