Как стать автором
Обновить

Управление зависимостями в Python: похоже, уже можно пользоваться

Время на прочтение8 мин
Количество просмотров32K
Всего голосов 34: ↑31 и ↓3+28
Комментарии71

Комментарии 71

Спасибо. Хотел попросить консультации у опытных питонистов. Я пилю научный проект с довольно узким применением — ссылка на GitHub. Как правильнее завернуть это безобразие для облегчения использования? Плюс у меня еще и две опциональные библиотеки — seaborn и pandas. И как будет выглядеть процесс установки и запуска? Сейчас задумано клонирование репозитория и запуск из консоли с чем-то вроде
python3 dab_deconv_area.py -p /home/meklon/Data/sample/test/ -t 35 -e 89 -s -a
Напишите setup.py для вашего проекта, там можно будет указать и зависимости, и точку входа (команда ляжет куда-то в /usr/bin), и многое другое. Как пример привожу собственный setup.py, документация тут.

После написания setup.py ваш проект можно будет загрузить на pypi.python.org и ставить оттуда вот так:
pip install (project name)


Или можно ставить прямо из мастер (или любой другой) ветки вашего репозитория:
pip install https://api.github.com/repos/meklon/DAB_analyzer/tarball/master
О. Прекрасно. То есть по факту можно будет запускать как я написал выше, но не важно из какого локального каталога?
Даже python3 не надо будет писать. Примерно так:
dab_deconv_area -p /home/meklon/Data/sample/test/ -t 35 -e 89 -s -a
Полный восторг) спасибо. Пошел читать документацию.
Кстати, хотел еще попросить бросить взгляд на документацию на гитхабе. Этого достаточно для пользователя?
Я думаю вполне — я бы разобрался.
Отлично, спасибо.
Кстати, а что с Windows? Сейчас утилита вроде как кроссплатформенная и относительно всеядна в плане версий python. pip install тоже как-то реализуется? Я переживаю, потому, что основной пользователь — биолог-исследователь. Хочется проще.

Вы можете сделать standalone-сборку своей программы, например, с помощью cx_freeze.
Для Windows ещё есть неофициальные сборки wheel-пакетов: http://www.lfd.uci.edu/~gohlke/pythonlibs/

Попробую, спасибо. GUI очень писать не хочется, надеюсь мануал к консоли будет достаточно понятен. Одного коллегу я консультировал, но он сам линуксоид.

По хорошему, проект должен иметь такую структуру:


  1. Библиотечный пакет или модуль, который предоставляет API ко всей вычислительной части
  2. Приложения, утилиты, примеры (консольные и/или GUI), а также тесты, которые используют этот API

То есть разработку проекта надо вести снизу-вверх. Сначала пишется библиотека, а потом над ней утилиты и приложения.

Я очень старался писать аккуратно и следуя PEP 8, но с архитектурой, кажется, накосячил. Собственно, я до этого вообще софт не писал ибо врач. Надо думать. Мне явно потребуется расширять функциональность, но миллион ключей в консоли уже тяжело ложатся на принцип KISS. Хотя и позволяют запилить какой-нибудь скрипт на баше поверх.
Миллион ключей — не обязательно проблема. В биоинформатике многие уважаемые программы запускаются исключительно (или по крайней мере преимущественно) одной командой с горой ключей. Причина, я полагаю, в том, что если команда всего одна — то гораздо проще вставить программу в пайплайн, не заморачиваясь общением с её интерфейсом. Но при этом анализ должен очень точно настраиваться под нужды пользователя, так что команда получается гигантская.
Всем этим в консоли, конечно, пользуется скорее специально обученный биоинформатик, а не просто биолог без навыков программирования/линуксоводства. У меня один коллега вообще здорово удивился, увидев локальный BLAST. Но если вы в любом случае не собираетесь делать полноценный GUI — то тонна ключей лучше, чем что-то интерактивное на curses или, избави Господи, текстовое меню в консоли.
Вы только что избавили меня от ошибки с меню консольным) принцип программы в выделении из среза, окрашенного несколькими красителями только одного. Например, DAB-хромогена из пары DAB+гематоксилин. И потом считает пакетно площадь надпорогового по интенсивности окрашивания. Я хочу ввести возможность выбирать свой вектор красителя, вместо захардкоженного. Если не делать меню, то это корректнее делать дополнительным файлом с NumPy массивами красителей? Как корректнее импортировать и выбирать?

В голову приходит вариант импорта по номеру вектора в файле. Что-то типа ключа --vector 3, где 3 это, например, массив с вектором эозина.
НЛО прилетело и опубликовало эту надпись здесь
Дефолтные значения в коде. Как наиболее распространенные и оптимальные. Там преимущественно надо пороги крутить, если снимки нетипичные по экспозиции/интенсивности окраски. Основная идея сделать более универсальный инструмент для оценки любого красителя. Сейчас хардкодом вбит вектор именно нашего лабораторного DAB-хромогена.
НЛО прилетело и опубликовало эту надпись здесь
Про словарь не думал, спасибо.
Ме бы еще понять, как проще всего внешний конфиг парсить из программы. В идеале можно выводить в консоль список найденных векторов по ключу вроде --stain_list.
НЛО прилетело и опубликовало эту надпись здесь
То, что надо, спасибо. Какие-то особые грабли ожидаются, с учетом того, что мои вектора для крастелей это NumPy массивы?
 matrixVectorDabHE = np.array([[0.66504073, 0.61772484, 0.41968665],
                                  [0.4100872, 0.5751321, 0.70785],
                                  [0.6241389, 0.53632, 0.56816506]])


Хранение напрямую в виде человекочитаемых переменных сразу Python выглядит весьма разумно. Хотя несколько неожиданно)
Спасибо.
Я бы посоветовал не делать эти массивы бинарными, а сделать человекочитаемыми, например CSV, JSON или YAML. Они у вас небольшие и на производительности это не скажется. При этом с точки зрения программирования — файлы в этих форматах вы прочитаете одной строкой на питоне.
Чтобы подкрепить слова делом, прислал PR =)
НЛО прилетело и опубликовало эту надпись здесь
О. прекрасно. То есть после импорта у меня в Global Scope подтянутся переменные, которые были объявлены как константы в configs.parameter_set_bender_experiment_keelallhumans?
НЛО прилетело и опубликовало эту надпись здесь
Ага. А <parameter_name> может быть переменной, полученной из args.parser? По идее аргументом из консоли выбирают вектор.
Кажется понял. Не распихивать векторы по отдельным переменным, а сделать один словарь stain_vectors, откуда уже дергать по индексу, полученному при парсинге аргументов командной строки. И индексы словаря можно будет выбрасывать спокойно в --help где-то. Огромное спасибо) тяжело без опыта разработки. Стараешься без лапши запутанной писать, но по мере разрастания проекта все начинает дико усложняется. Особенно ужасает непрерывно меняющееся техническое задание.
НЛО прилетело и опубликовало эту надпись здесь
Короче, пошел рисовать архитектуру)
если вы сделаете конфиги в виде питонячих файлов, пользователям будет сложно модифицировать ваши конфиги — они встанут вместе с вашей библиотекой глубоко в систему. Я считаю, что лучше сделать в человекочитаемом общепринятом формате: JSON, YAML, TOML, INI. Все они парсятся одной строкой на питоне, после подключения соответствующих библиотек.
Да, я уже почитал документацию. Раздражают различия Windows/Linux. Проще Windows сделать вторичным.
Мне еще нужно, чтобы конфиг легко читался и редактировался руками.
> основной пользователь — биолог-исследователь

Python всё еще торт :) В 1997 на третьем курсе физфака я, писавший до того на Perl, был вынужден познакомиться с Python, потому что на нём была написана реализация формата хранения результатов экспериментов в кристаллографии :) Уже тогда он в хвост и гриву использовался научным сообществом. В отличие от personal home pages, только-только начавших стесняться своего названия и ставших акронимом. И лексического анализатора, созданного для тех, кому стало мало awk и sed :)

А ведь еще даже не было SciPy :)
Python прекрасен. Я, блин, врач по образованию. Но понятно же. На редкость удобный язык. Да, небыстрый. Но подпилив кое-где, используя NumPy и прочие быстрые библиотеки, все отлично работает. Все равно я ему данные не смогу лопатой подбрасывать с такой скоростью, с какой он считает. Я еще заморочился с multiprocessing, доволен как слон. Особенно дома в 4 потока бодро молотит. Но даже на рабочем Celeron у меня один сэмпл-фотография обрабатывается в среднем за 800 мс.
Могу посоветовать совет собрать virtualenv со всеми зависимостями, потом уже в ней
pip freeze > all_requirements.txt

Руками вычистить опциональный пакеты и обозвать requirements.txt

Залить в репу и дальше уже тем кто ставит надо будет выполнить:
pip install -r requirements.txt
или
pip install -r all_requirements.txt
Как вариант. На Ubuntu и деривативах зависимости через apt-get заливаются. У меня вполне типовые библиотеки.

То что я предложил больше подходит для venv, ну и когда нужна версия библиотеки отличная от той, что есть в репозитории дистрибутива.


Сам придерживаюсь такого правила:
Глобально — apt
Virtualenv — pip

Видимо, был не прав. Я pip через did запускаю.
Можете также взглянуть на PyBuilder — попытка сделать maven-like систему сборки для Python-a. Может быть пригодится…
Посмотрю, спасибо.
Нужны тулзы для автоматического создания и обновления “setup.py”. Ну или что-нибудь вроде “setup.python.json” или чего-нибудь подобного, чтобы не было необходимости писать код только ради пары строк метаданных.

На самом деле давно уже предлагают вообще избавиться от setup.py. Вот недавно даже PEP написали: https://www.python.org/dev/peps/pep-0518/


Лично моё мнение: wheel-пакеты — это лучшее, что случилось с инфраструктурой зависимостей Python за последнее время. Думаю, направление выбрано верное.

Черт, TOML… Ничему питонистов жизнь не учит. Когда CPython решали на какую систему контроля версий переезжать, тоже было несколько вариантов, все тщательно обсудили и выбрали… то что выбрали. И теперь закономерно огребли проблем и (ура! 2016 год на дворе) решили все-таки переехать на GitHub. Думаю, и здесь глядишь через год-другой формат поменяют на JSON/YAML когда окажется что никто его не использует.
P.S. я сам питонист.

Они там приводят аргументы в защиту TOML, что он простой, гибкий и human-usable, что он используется в Cargo и т. д. JSON им кажется плохо читаемым, а YAML слишком сложным. Причем они не настаивают прямо вот на TOML (хотя и рекомендуют) и приводят примеры конфигураций также и на JSON/YAML. В любом случае, в Python из коробки сейчас есть только JSON.

НЛО прилетело и опубликовало эту надпись здесь
1) Когда они переезжали (PEP датирован 2009 годом), Mercurial был гораздо проще для пользователей других систем контроля версий, чем Git, и GitHub (заработал в 2008-м) еще не был таким обязательным ;)

2) Wheel — это zip-архив, как и многие другие схожие форматы (ну, вспомним хотя бы jar). Метеданные внутри архива — это другое дело, там JSON/YAML был бы в тему, но скорее всего формата ключ: значение на очень многие задачи будет хватать.
Небольшое упущение: Python 3.x и компиляция под Windows требует немного другого подхода. Детали здесь: https://wiki.python.org/moin/WindowsCompilers

Остальное — оч-ч-чень интересно, надо пробовать и разбираться в деталях.
уже нельзя говорить, что у других языков программирования все «намного лучше»

Вот не обобщали бы на всех-то… это всегда выходит неправда.

У кого сейчас намного лучше, если не секрет?

Ну если по-простому — то почти у всех языков на платформе JVM намного лучше. Скажем, до groovy grapes Python еще далеко по удобству. Это вовсе не значит, что у Python все плохо — просто есть к чему стремиться. Я прекрасно понимаю, что если у вас зависимость это скажем native бинарники, а не portable код на Python — то этого не так просто добиться.


Скажем, вы можете написать:


!/usr/groovy/latest/bin/groovy

@Grapes([
@GrabConfig(systemClassLoader=true)
, Grab(group='net.sourceforge.jtds', module='jtds', version='1.3.1')
, Grab(group='org.postgresql', module='postgresql', version='9.3-1100-jdbc41')
, Grab(group='com.sybase', module='jconn3', version='6.05')
])


import groovy.sql.*


import net.sourceforge.jtds.jdbcx.*


т.е. динамически подключить зависимость (в данном случае — драйвер базы данных), и тут же ее импортировать и использовать.

Пришла оповещалка о том, что кто-то меня упомянул — значит опять про Grapes пишут :)
Как правило, создатели нового языка программирования уделяют этому не очень много внимания… Единственным на моей памяти исключением является node.js

Немного непонятно почему здесь авторы node.js приравнены к авторам языка Javascript. Или это одни и те же люди?

Тут скорее node.js назван отдельным языком

> Как обычно, у Rust с Cargo все почти идеально
Кроме того что многие зависимости рассчитывают на nightly или по крайней мере unstable.

Учитывая что нестабильный функционал есть только в ночных сборках, одного без другого не бывает.


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

но ведь никто из читающих эти строки не использует Rust?

Ну уж нет, как минимум один гордый растафарианин (или как там договорились самоназываться?) читает это. Пускай и только в хобби-проекте использую)

Выполнял тестовое задание перед интервью, использовал numpy, получил отзыв:

«Минусы:
1. Поставить библиотеку для обработки статистики оказалось делом не тривиальным (пришлось покопаться в инете), в итоге нужно скачать отсюда пакет (numpy-1.11.1+mkl-cp27-cp27m-win32.whl) для установки numpy и выполнить команду «pip install numpy-1.11.1+mkl-cp27-cp27m-win32.whl» в папке где лежит пакет.
»

Понимаете, не тривиальное это дело, собранное колесо поставить. А вы говорите зависимости.
А почему нельзя стандартно что-то вроде apt-get install python3-numpy-dev?
Блин. Забываю уже. Привык к Линуксу за последние годы.

Собрать numpy на Windows из исходников — нетривиальная задача. Поэтому есть неофициальные собранные пакеты с MKL. Без MKL есть официальные wheel-пакеты на PyPI, поэтому не понятно, что за сложности были у тех, кто давал тестовое задание. Возможно, это было давно, когда официальных wheel-пакетов ещё не было.


Сейчас, если не нужна производительность MKL, можно просто делать так:


pip install numpy

А почему нельзя стандартно что-то вроде apt-get install python3-numpy-dev?

В репах обычно старая версия

Насчет старой версии согласен, но субъективно, далеко не всегда bleeding edge нужен. По крайней мере, я редко с таким сталкивался.
pip install numpy
На винде это легко выливается в танцы с поиском и установкой нужного компилятора. Особенно на 64 битной системе. Может быть вот прямо сейчас это изменилось в лучшую сторону, но еще этой весной все было очень плохо.

Я выше пишу:


Собрать numpy на Windows из исходников — нетривиальная задача.

Сейчас на PyPI уже лежат официальные собранные wheel-пакеты под винду: https://pypi.python.org/pypi/numpy
Компилятор не нужен, там уже собранные бинарники в пакете.


Другое дело, что они собраны без MKL, а MKL сильно улучшает производительность вычислений над массивами.

Да, извините, невнимательно прочитал ваш комментарий.

Numpy+MKL для Windows обычно отсюда брали — полет нормальный ;)

Куда лучше было бы реализовать pip по принципу npm или composer, где пакеты качаются в специальную директорию с кодом проекта, для питона, например, site-packages, а sys.path первым путем поиска записывать локальную директорию, чтобы нормально импорт работал.

Что касается virtualenv, как по мне это главная проблема в питоне. Virtualenv – софт с плохим дизайном, который даже не пытается решать проблемы предоставляя сложное решение с хаком консоли и копированием половины питона и при этом не позволяя выбирать в проекте версию интерпритатора. Чтобы использовать другой питон нужно ставить pyenv, который тоже имеет фатальный недостаток – отсутствие кроссплатформенности. Если бедный разработчик хочет чтобы его проект работал и под виндой тоже, есть и такие два пакета: pywin и anyenv. Ну и так дальше в глубь ада.

В общем количество альтернативных реализаций virtualenv показывает на проблемы инструмента, которые пока никто не решает.

Согласен: пытался пользоваться как virtualenv, так conda (из научного дистрибутива Anaconda) — больше проблем нежели чем решений.


Наверное, на сегодняшний день лучше все путями шаманить… Печаль.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий