Python package entry points

Точки входа в Python

Многие думают, что точки входа это такие инструкции в setup.py, которые позволяют сделать пакет доступным для запуска из командной строки. Это, в целом, верно, но возможности точек входа не ограничиваются этим.

Ниже я покажу как можно реализовать систему плагинов для пакета, чтобы другие люди могли с ним взаимодействовать или, например, расширять его функциональность динамически.

Осторожно: специфический юмор далее по тексту.

ООО «Змейка»

Поздравляю! Вас только что назначили главой ООО «Змейка». Это очень ответственная должность, ударить в грязь лицом нельзя, а значит, нужно как можно скорее дать указание отделу разработки приступить к созданию прототипа продукта. И вот, лучшие умы компании начинают работу над 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 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 

На конференции, посвящённой итогам года, вы выступаете, демонстрируя новейшую разработку:

Читайте также:  PHP Login Form

Змейка в каждый дом

Змейка завоёвывает мир. Компания провела IPO и была оценена в рекордные 60 миллиардов долларов. Хипстеры требуют новую, стильную, модную и молодёжную змейку. А раз есть спрос, будет и предложение:

"""Печатает 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 ; `:. `-, _.-~~^^~:. `. ; _,--~~~~-._ `:. ~. .~ `. .` ;' .:` `: `:. ` _.:-,. `. .' .: :' _.-~^~-. `. `..' .: `. ' : .' _:' .-' `. :. .: .'`. : ; : `-' .:' `. `^~~^` . `. ; ; `-.__,-~ ~-. ,' ': '.__.` :' ~--..--' ':. .:' '. ___.:' 

Транснациональная Змейка

Миллионы человек не мыслят свой день без змейки. Даже после поглощения Гугла ресурсов ООО «Змейка» не хватает, чтобы удовлетворять потребности пользователей по всему миру. Похоже настало время дать людям возможность создавать собственных змеек на базе нашей инфраструктуры.

"""Печатает 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. Каждая такая змейка зарегистрирована под названием её типа, что позволяет выбирать нужную змейку в зависимости от параметров консоли.

Читайте также:  Html body jquery css

Всё самое главное происходит внутри get_sneks. Вызов pkg_resources.iter_entry_points(‘snek_types’) позволяет пройтись по всем точкам входа, зарегистрированным под именем «snek_types» где-либо. Таким образом, любой сторонний пакет сможет в своём setup.py создать точку входа «snek_types», чтобы быть загруженным нашим скриптом.

Мы рассказали о «snek_types» нашим коллегам из ООО «Змеиные решения», и они тут же начали создавать змейку своей мечты. Вот каким получился их пакет cute_snek.py:

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

А вот как они реализовали свой setup.py, чтобы наша 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, они могут вывести свою змейку из пакета cute_snek за счёт её динамической загрузки по точке входа:

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

Змейка 2.0

Пока всё внимание высшего руководства уходит на разборки с налоговой инспекцией и антимонопольной службой, отдел разработки наконец-то может выкроить немного времени на рефакторинг кода.

Читайте также:  Html to chm online

Главный системный архитектор понял, что если сторонние змейки могут быть загружены как плагины, значит, так же могут быть загружены и встроенные змейки.

Уберём особую обработку встроенных змеек:

--- 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| \/ /~ \_/ \ \____|__________/ \ \_______ \ `\ \ \ | | \ / / \ / / \ / / \ \ / / \ \ / / _----_ \ \ / / _-~ ~-_ | | ( ( _-~ _--_ ~-_ _/ | \ ~-____-~ _-~ ~-_ ~-_-~ / ~-_ _-~ ~-_ _-~ ~--______-~ ~-___-~ 

Источник

Оцените статью