В большинстве популярных языков программирования и экосистем с зависимостями все плохо. Как правило, создатели нового языка программирования уделяют этому не очень много внимания: просто потому, что в новом языке еще нет сотен тысяч библиотек для разных архитектур и версий, нетривиальным образом зависящих друг от друга. А когда эти сотни тысяч библиотек появляются – уже поздно что-нибудь менять.

Единственным на моей памяти исключением является node.js, авторы которой разработали «с чистого листа» на удивление удачную систему управления зависимостями. Ну, как удачную? Проблем там тоже много, начиная автовыполняемыми скриптами и заканчивая переходом от древовидной к flat структуре в 3-й версии. Но по сравнению с тем, что на тот момент было в других языках, нода — это прорыв.

Совсем недавно экосистема пополнилась новой утилитой rnpm, которая позволяет одной командой устанавливать React Native зависимости. В которых, на секундочку, может быть бинарный код для android и ios. Для разных архитектур. И все это работает из коробки. Мы в Voximplant хорошо знакомы с этой штукой: с ее помощью ставится наш собственный React Native SDK.

Вашему вниманию предлагаем интересную статью, опубликованную всего два дня назад, в которой очень подробно рассказывается про управление зависимостями в Python. Про историю развития. Про проблемы. И, что самое ценное — про то, как сообщество их решает. Под катом адаптированный для Хабра перевод и возможность обсудить печальную тему зависимостей. И не только для Python.

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

Потому что мы починили работу с зависимостями. Если ты разработчик и создаешь или используешь Python библиотеки, то теперь это делается легко и без боли. Я говорю это, потому что в течении долгого времени средства Python для работы с зависимостями были… с проблемами. Это уже не так, но многие люди продолжают читать о «проблемах с зависимостями у Python» и думают, что ничего не поменялось. Пора все рассказать.

Небольшой исторический экскурс. С зависимостями у Python дело обстояло примерно так…

Рассвет


Python увидел свет в те времена, когда добавление зависимости означало долгое путешествие в киберспейс. Для начала нужно было дождаться освобождения телефонной линии. Затем позвонить провайдеру. Позвонить по модему, что характерно. После боя с SLIP или PPP клиентом можно было задать вопрос в одну из групп, знает ли кто-нибудь хороший gopher-сайт, где можно найти библиотеку для решения стоящей перед тобой задачи. После чего можно было отключиться от интернета и подождать несколько десятков часов: вдруг кто-нибудь да ответит. Если повезло, то можно было поставить закачку на ночь.

Никакого pip search тогда не было!

Для того времени подход Python к управлению зависимостями был удивительно прозорливым. Директива ‘import’ и расширяемая система загрузки модулей позволяла подключать зависимости откуда угодно.

Вместе с версией 2.0 Python (октябрь 2000 года) состоялся релиз Distutils. С его помощью разработчики смогли абстрактно описывать их коллекции модулей и создавать пригодные для распространения коллекции модулей и пакетов. И снова, это было очень, очень прозорливое решение. В те времена ни о чем подобном не было и речи.

Перематываем время к 2004 году. Создание setuptools для решения типовых задач, с которыми сталкиваются разработчики open source при распространении своих модулей через интернет. В 2005 была добавлена утилита easy_install для автоматического определения зависимостей и скачивания их в нужные директории.

Темные века


К сожалению, вместе с простыми механизмами описания зависимостей, setuptols притащили с собой чудовищное количество сложности. Автор посчитал, что директива ‘import’ должна работать немного по-другому, и установка setuptools изменила ее поведение. По сравнению с обычной директивой ‘import’, версия setuptools поддерживала работу с несколькими версиями одной и той же зависимости в рамках одной программы. Тогда это казалось замечательной идеей. Но время показало, что это не так. Более того, схожая идея возможности установки нескольких версий библиотеки на один компьютер (а не одновременно для одной программы) является важной и нужной штукой.

В дополнение к этому идеологическому отходу от стандартной семантики Python, setuptools имела проблемы с майнтейнером. Точнее, с отсутствием майнтейнеров. Она стала критичной частью Python экосистемы как раз в тот момент, когда автор решил заняться другими проектами – совершенно несвязанными с программированием. Довольно долго никто не мог договориться, кто и как будет поддерживать проект. Который, к тому времени, с одной стороны был уже форкнут, а с другой стороны, во многих дистрибутивах «окаменела» старая и глючная версия.

С 2008 по 2012 года управление зависимостями в Python представляло из себя не лучшее зрелище. Пользоваться им было по меньшей мере болезненно. Было непонятно, какие библиотеки и утилиты использовать, в какие стоит инвестировать свое внимание и изучать. Ручное управление зависимостями было утомительно, тогда как автоматизация требовала множество слабо документированных обходных путей.

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

В то же самое время все большую популярность стали завоевывать новые языки и экосистемы, в которых управление зависимостями было реализовано более-менее правильно с самого начала и которые имели лучшую поддержку распространения бинарных файлов. Эти решения выучили свой урок на ошибках Python и Perl.

И, наконец, Python Package Index. Сайт, хранящий и распространяющий все open source библиотеки, созданные сообществом Python. Не более чем proof-of-concept, который был запущен слишком рано, не имел никаких ресурсов для развития своей инфраструктуры и слишком часто становился оффлайн.

Все складывалось не лучшим образом для Python.

Интерлюдия

Вот мы и подошли к тому моменту, когда говорят, что “управление зависимостями в Python — #$@#@@!”. Большинство таких высказываний — устаревшая информация, описывающая этот период времени. Множество блогпостов с жалобами, высоко ранжируемые поисковыми системами по запросу “проблемы”. Те, кто использовал Python в это время и перешел на использование других языков, часто ворчат о том, как ужасно было управлять зависимостями, насколько сломана была экосистема и как часто лежал PyPI. Хуже всего, в сети есть множество советов по обходным путям решения проблем, которые уже давно не нужны, но все еще показываются поисковыми системами в топе выдачи. Следование таким советам ломает пользователям рабочее окружение и только усугубляет ситуацию.

Восставшие из пепла


И посредине этого великого полома ряд разработчиков героически, молча, медленно все чинили, по одному вгрызаясь в багрепорты. Стартовал проект ‘pip’, многочисленные мейнтейнеры которого убрали большую часть сложности, что принесла ‘easy_install’, и исправили многие ее недостатки. Donald Stufft взялся сразу за Pip и PyPI, исправив старые уязвимости и сделав систему более устойчивой. Daniel Holth написал PEP для формата ‘wheel’, который позволяет распространять бинарный код вместе с библиотеками. То есть, другими словами, позволяет пользователями без настроенного компилятора “C” устанавливать пакеты, которые в противном случае потребуют этот компилятор для сборки.

В 2013 году setuptools снова объединился со своим форком distribute, что позволило вендорам операционных систем обновить системы работы с зависимостями и дать пользователям современные инструменты. Модуль “ensurepip” был включен в Python Core дистрибьюцию для версий 2.7 и 3.3, что позволило пользователям с более-менее современной версией Python одной командой получить себе работающее окружение для работы с зависимостями.

Новый Ренессанс

Я не буду рассказывать про современные приемы работы с зависимостями. Этому посвящен отдельный вебсайт. Но я покажу, насколько это сейчас просто. Для любой современной версии Python, если вы хотите получить работающее окружение без админских прав, все что вам нужно это:

$ python -m ensurepip --user
$ python -m pip install --user --upgrade pip
$ python -m pip install --user --upgrade virtualenv

Для каждого проекта вы можете создать собственную «песочницу» virtualenv:

$ python -m virtualenv lets-go
$ . ./lets-go/bin/activate
(lets-go) $ _

Это все. Можно использовать pip, чтобы устанавливать любые зависимостями. Для установки большинства вам даже не потребуется компилятор! Более того, эти заклинания не зависят от версии Python: они будут работать с Python 2, Python 3, PyPy и даже Jython (примечание переводчика: сюрприз, да?).

На самом деле, часто вам даже не потребуется шаг с ‘ensurepip’, так как ‘pip’ будет уже установлен и настроен! Тем не менее, лучше выполнить это простое заклинание, вреда оно не нанесет.

Более продвинутые операции над зависимостями тоже упростились. Нужен компилятор «C»? Создатели операционных систем плотно работали с сообществом, чтобы сделать настройку компилятора максимально безболезненной:

$ apt install build-essential python-dev # ubuntu
$ xcode-select --install # macOS
$ dnf install @development-tools python-devel # fedora
C:\> REM windows
C:\> start https://www.microsoft.com/en-us/download/details.aspx?id=44266

Ладно-ладно, последний шаг не такой уж безболезненный. Но компилятор хотя бы есть, бесплатен и устанавливается простым скачиванием с сайта! Хотите загрузить что-нибудь на PyPI? Для большинства проектов это будет вот настолько просто:

$ pip install twine
$ python setup.py sdist bdist_wheel
$ twine upload dist/*

Хотите собрать бинарные пакеты wheels? И для этого есть приложение (docker container, разумеется).

Что важно, можно уверенно говорить о высоком онлайне PyPI. А еще у них со дня на день будет новый, полностью переделанный сайт (примечание переводчика: еще один сюрприз).

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

Работа, которая нам предстоит


Текущая ситуация уже неплоха. Но ее нельзя назвать «замечательной». Что бы я еще хотел от нашей экосистемы:

  • Тулзы для установки на компьютеры конечных пользователей могут быть лучше.

  • Pip не повредит графический пользовательский интерфейс, чтобы его можно было использовать без заклинаний командной строки (примечание переводчика: и тут Остапа понесло…)

  • Нужны тулзы для автоматического создания и обновления “setup.py”. Ну или что-нибудь вроде “setup.python.json” или чего-нибудь подобного, чтобы не было необходимости писать код только ради пары строк метаданных.

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

  • PyPI должен автоматически собирать «wheels» для всех платформ по факту загрузки sdists пакета. Да, это большая и амбициозная задача, но подумайте, насколько она упростит работу с зависимостями!

Я могу так долго продолжать. Есть множество способов улучшить работу с зависимостями в Python.

Послесловие

Что я хотел сказать этим лонгридом. Ситуация с зависимостями в Python далека от идеала, но уже нельзя говорить, что у других языков программирования все «намного лучше». Для Go продолжаются обсуждения разных вариантов управления зависимостей и ситуация с “CGo” далека от идеала. У Node собственные горячо обсуждаемые проблемы с культурой управления зависимостями и тулчейном. Hackage крут и все такое, но время сборки достигает поистине астрономических значений. Как обычно, у Rust с Cargo все почти идеально – но ведь никто из читающих эти строки не использует Rust?

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

По моему мнению, любое утверждение о том, что в каком-то языке работа с зависимостями намного лучше чем в Python, скорее всего устарело. Сейчас зависимостями в Python уже можно пользоваться, и это не больно.. Конечно, может быть ещё лучше, но над улучшением работают множество программистов, и все основные барьеры, которые препятствовали дальнейшему развитию, они уже успешно убрали.

Пользуйтесь virtualenv! Хакните себе немного setup.py! Если последний раз вы работали с зависимостями в Python давно – попробуйте сейчас. Обещаю, все стало намного лучше.
Поделиться с друзьями
-->

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


  1. Meklon
    16.08.2016 13:23
    +2

    Спасибо. Хотел попросить консультации у опытных питонистов. Я пилю научный проект с довольно узким применением — ссылка на GitHub. Как правильнее завернуть это безобразие для облегчения использования? Плюс у меня еще и две опциональные библиотеки — seaborn и pandas. И как будет выглядеть процесс установки и запуска? Сейчас задумано клонирование репозитория и запуск из консоли с чем-то вроде

    python3 dab_deconv_area.py -p /home/meklon/Data/sample/test/ -t 35 -e 89 -s -a
    


    1. Direvius
      16.08.2016 14:26
      +7

      Напишите 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


      1. Meklon
        16.08.2016 20:48

        О. Прекрасно. То есть по факту можно будет запускать как я написал выше, но не важно из какого локального каталога?


        1. Direvius
          16.08.2016 22:41

          Даже python3 не надо будет писать. Примерно так:
          dab_deconv_area -p /home/meklon/Data/sample/test/ -t 35 -e 89 -s -a


          1. Meklon
            16.08.2016 23:25

            Полный восторг) спасибо. Пошел читать документацию.


          1. Meklon
            16.08.2016 23:36

            Кстати, хотел еще попросить бросить взгляд на документацию на гитхабе. Этого достаточно для пользователя?


            1. Direvius
              17.08.2016 17:34

              Я думаю вполне — я бы разобрался.


              1. Meklon
                17.08.2016 17:57

                Отлично, спасибо.


      1. Meklon
        16.08.2016 20:51

        Кстати, а что с Windows? Сейчас утилита вроде как кроссплатформенная и относительно всеядна в плане версий python. pip install тоже как-то реализуется? Я переживаю, потому, что основной пользователь — биолог-исследователь. Хочется проще.


        1. iroln
          16.08.2016 20:58

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


          1. Meklon
            16.08.2016 21:17

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


            1. iroln
              16.08.2016 21:25

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


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

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


              1. Meklon
                16.08.2016 23:29

                Я очень старался писать аккуратно и следуя PEP 8, но с архитектурой, кажется, накосячил. Собственно, я до этого вообще софт не писал ибо врач. Надо думать. Мне явно потребуется расширять функциональность, но миллион ключей в консоли уже тяжело ложатся на принцип KISS. Хотя и позволяют запилить какой-нибудь скрипт на баше поверх.


                1. synedra
                  17.08.2016 06:44

                  Миллион ключей — не обязательно проблема. В биоинформатике многие уважаемые программы запускаются исключительно (или по крайней мере преимущественно) одной командой с горой ключей. Причина, я полагаю, в том, что если команда всего одна — то гораздо проще вставить программу в пайплайн, не заморачиваясь общением с её интерфейсом. Но при этом анализ должен очень точно настраиваться под нужды пользователя, так что команда получается гигантская.
                  Всем этим в консоли, конечно, пользуется скорее специально обученный биоинформатик, а не просто биолог без навыков программирования/линуксоводства. У меня один коллега вообще здорово удивился, увидев локальный BLAST. Но если вы в любом случае не собираетесь делать полноценный GUI — то тонна ключей лучше, чем что-то интерактивное на curses или, избави Господи, текстовое меню в консоли.


                  1. Meklon
                    17.08.2016 09:06

                    Вы только что избавили меня от ошибки с меню консольным) принцип программы в выделении из среза, окрашенного несколькими красителями только одного. Например, DAB-хромогена из пары DAB+гематоксилин. И потом считает пакетно площадь надпорогового по интенсивности окрашивания. Я хочу ввести возможность выбирать свой вектор красителя, вместо захардкоженного. Если не делать меню, то это корректнее делать дополнительным файлом с NumPy массивами красителей? Как корректнее импортировать и выбирать?

                    В голову приходит вариант импорта по номеру вектора в файле. Что-то типа ключа --vector 3, где 3 это, например, массив с вектором эозина.


                    1. alsii
                      17.08.2016 13:33

                      Ни в коей мере не считаю себя специалистом по Python, но рискну вставить свои 5 копеек. Мне кажется в Вашем случае разумно будет сделать файл с настройками. В первом приближении настройки — это просто список ключей с их значениями. В /etc/dab_deconf_area.conf можно положить настройки по умолчанию.
                      Чтобы не напрягать пользователя можно сделать ключ --save, который будет сохранять все настройки, с которыми запущена программа куда-нибудь в ~/dab_deconf_area/default.conf.
                      Можно еще сделать сохраниене настроек (пресетов?) под разными именами, например так: --save preset-name сохраняет в ~/dab_deconf_area/preset-name.conf. --preset preset-name загружает пресет и запускает обработку с данными пресета. Можно сделать так, что сохраненные в пресете значения будут иметь приоритет над тем, что в ~/dab_deconf_area/default.conf, а те над /etc/dab_deconf_area.conf. Ну и ключи указанные в командной строке имеют наивысший приоритет. Если вы сделаете ключ --dry-run, который прогонять программу «всухую», без реальной обработки, то пользователь сможет копировать пресеты с изменениями:
                      dab_deconf_area --dry-run --preset preset1 --ke1 new_value --save preset2 # Копируем preset1 в preset2, но меняем значение ключа key1.
                      Что-то я уже много написал, а у меня еще столько идей :) Пожалуй остановлюсь, а то меня реально понесло :)
                      Да, и никто не запрещает редактировать файлы настроек руками. А если сделать короткие варианты ключей: --preset = -p, --save = -s, то пользователи будут благодарны.


                      1. Meklon
                        17.08.2016 15:16

                        Дефолтные значения в коде. Как наиболее распространенные и оптимальные. Там преимущественно надо пороги крутить, если снимки нетипичные по экспозиции/интенсивности окраски. Основная идея сделать более универсальный инструмент для оценки любого красителя. Сейчас хардкодом вбит вектор именно нашего лабораторного DAB-хромогена.


                    1. kinazarov
                      17.08.2016 14:06

                      А может сделать понятнее, например с промежуточным словарем типа {eozyne: 3}
                      И тогда команда будет --vector «eozyne»


                      1. Meklon
                        17.08.2016 15:12

                        Про словарь не думал, спасибо.


                      1. Meklon
                        17.08.2016 15:23

                        Ме бы еще понять, как проще всего внешний конфиг парсить из программы. В идеале можно выводить в консоль список найденных векторов по ключу вроде --stain_list.


                        1. kinazarov
                          17.08.2016 15:55

                          На выбор могу предложить несколько вариантов:

                          pickle
                          ConfigParser 1 2

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

                          #!/bin/python
                          dry_run=True
                          stain_list=list(
                              ("eozyne",3)
                              ("ophegeen",4)
                          )
                          


                          А также использовать (например sqlite) для хранения очереди пакетов входных и обработанных данных для потоковой обработки результатов серии экспериментов.
                          Один относительно простой модуль (возможно с ncurses-подобной менюхой) регистрирует данные в БД для обработки ядром, которое их по очереди берет из БД и туда же отдает данные после обработки.
                          Таким образом можно будет заранее исключить необходимость создания пакетных файлов для выполнения одной и той же программы но для разных каталогов с исходными данными и разными ключами для каждого каталога.


                          1. Meklon
                            17.08.2016 16:02

                            То, что надо, спасибо. Какие-то особые грабли ожидаются, с учетом того, что мои вектора для крастелей это NumPy массивы?

                             matrixVectorDabHE = np.array([[0.66504073, 0.61772484, 0.41968665],
                                                              [0.4100872, 0.5751321, 0.70785],
                                                              [0.6241389, 0.53632, 0.56816506]])
                            


                            Хранение напрямую в виде человекочитаемых переменных сразу Python выглядит весьма разумно. Хотя несколько неожиданно)


                            1. iroln
                              17.08.2016 16:24

                              numpy-массивы можно писать в файлы и читать из файлов. Вот документация: http://docs.scipy.org/doc/numpy/reference/routines.io.html


                              Вдруг пригодится.


                              1. Meklon
                                17.08.2016 16:36

                                Спасибо.


                              1. Direvius
                                18.08.2016 18:25

                                Я бы посоветовал не делать эти массивы бинарными, а сделать человекочитаемыми, например CSV, JSON или YAML. Они у вас небольшие и на производительности это не скажется. При этом с точки зрения программирования — файлы в этих форматах вы прочитаете одной строкой на питоне.


                                1. Direvius
                                  18.08.2016 19:15
                                  +1

                                  Чтобы подкрепить слова делом, прислал PR =)


                            1. kinazarov
                              17.08.2016 16:31

                              Для такого способа вот подсказка: создаешь в каталоге с программой еще один каталог (например «configs»). В нем пустой файл с именем __init__.py и нужное количество модулей, которые одновременно являются конфигами. А потом можно удобно использовать синтаксис импорта пакетов примерно так:

                              import configs.parameter_set_bender_experiment_keelallhumans

                              пример


                              1. Meklon
                                17.08.2016 16:40

                                О. прекрасно. То есть после импорта у меня в Global Scope подтянутся переменные, которые были объявлены как константы в configs.parameter_set_bender_experiment_keelallhumans?


                                1. kinazarov
                                  17.08.2016 16:46

                                  Не в глобал. Они будут доступны как

                                  configs.parameter_set_bender_experiment_keelallhumans.<parameter_name>
                                  


                                  Для импорта в глобал чуть-чуть иначе:
                                  from configs.parameter_set_bender_experiment_keelallhumans import *
                                  print(matrixVectorDabHE)
                                  


                                  1. Meklon
                                    17.08.2016 17:00

                                    Ага. А <parameter_name> может быть переменной, полученной из args.parser? По идее аргументом из консоли выбирают вектор.


                                  1. Meklon
                                    17.08.2016 17:30

                                    Кажется понял. Не распихивать векторы по отдельным переменным, а сделать один словарь stain_vectors, откуда уже дергать по индексу, полученному при парсинге аргументов командной строки. И индексы словаря можно будет выбрасывать спокойно в --help где-то. Огромное спасибо) тяжело без опыта разработки. Стараешься без лапши запутанной писать, но по мере разрастания проекта все начинает дико усложняется. Особенно ужасает непрерывно меняющееся техническое задание.


                                    1. kinazarov
                                      17.08.2016 17:45

                                      Вот поэтому ядро с набором функций которые собственно числа перемалывают надо хранить в одном наборе модулей а все параметры/данные — в других наборах модулей.

                                      И вот тебе еще пара мыслишек:
                                      1. Сперва в глобал грузишь

                                      from configs.default import *
                                      

                                      а потом специфичный конфиг для нужного набора данных
                                      from configs.experiment_set_01 import *
                                      

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


                                      1. Meklon
                                        17.08.2016 17:58

                                        Короче, пошел рисовать архитектуру)


                                        1. Direvius
                                          18.08.2016 18:27
                                          +1

                                          если вы сделаете конфиги в виде питонячих файлов, пользователям будет сложно модифицировать ваши конфиги — они встанут вместе с вашей библиотекой глубоко в систему. Я считаю, что лучше сделать в человекочитаемом общепринятом формате: JSON, YAML, TOML, INI. Все они парсятся одной строкой на питоне, после подключения соответствующих библиотек.


                                          1. Meklon
                                            18.08.2016 19:39
                                            -1

                                            Да, я уже почитал документацию. Раздражают различия Windows/Linux. Проще Windows сделать вторичным.


                                          1. Meklon
                                            18.08.2016 19:46

                                            Мне еще нужно, чтобы конфиг легко читался и редактировался руками.


        1. cadmi
          22.08.2016 12:55

          > основной пользователь — биолог-исследователь

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

          А ведь еще даже не было SciPy :)


          1. Meklon
            22.08.2016 13:26

            Python прекрасен. Я, блин, врач по образованию. Но понятно же. На редкость удобный язык. Да, небыстрый. Но подпилив кое-где, используя NumPy и прочие быстрые библиотеки, все отлично работает. Все равно я ему данные не смогу лопатой подбрасывать с такой скоростью, с какой он считает. Я еще заморочился с multiprocessing, доволен как слон. Особенно дома в 4 потока бодро молотит. Но даже на рабочем Celeron у меня один сэмпл-фотография обрабатывается в среднем за 800 мс.


    1. Taragolis
      17.08.2016 14:01

      Могу посоветовать совет собрать virtualenv со всеми зависимостями, потом уже в ней
      pip freeze > all_requirements.txt

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

      Залить в репу и дальше уже тем кто ставит надо будет выполнить:
      pip install -r requirements.txt
      или
      pip install -r all_requirements.txt


      1. Meklon
        17.08.2016 15:13

        Как вариант. На Ubuntu и деривативах зависимости через apt-get заливаются. У меня вполне типовые библиотеки.


        1. Taragolis
          18.08.2016 11:10

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


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


          1. Meklon
            18.08.2016 11:29

            Видимо, был не прав. Я pip через did запускаю.


    1. ilgarm
      17.08.2016 14:22

      Можете также взглянуть на PyBuilder — попытка сделать maven-like систему сборки для Python-a. Может быть пригодится…


      1. Meklon
        17.08.2016 15:23

        Посмотрю, спасибо.


  1. iroln
    16.08.2016 15:18
    +1

    Нужны тулзы для автоматического создания и обновления “setup.py”. Ну или что-нибудь вроде “setup.python.json” или чего-нибудь подобного, чтобы не было необходимости писать код только ради пары строк метаданных.

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


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


    1. markhor
      16.08.2016 15:30

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


      1. iroln
        16.08.2016 15:46
        +2

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


      1. alsii
        16.08.2016 15:50

        Нужно больше стандартов!


      1. nikolay_karelin
        16.08.2016 15:53
        +1

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

        2) Wheel — это zip-архив, как и многие другие схожие форматы (ну, вспомним хотя бы jar). Метеданные внутри архива — это другое дело, там JSON/YAML был бы в тему, но скорее всего формата ключ: значение на очень многие задачи будет хватать.


  1. nikolay_karelin
    16.08.2016 15:23
    +2

    Небольшое упущение: Python 3.x и компиляция под Windows требует немного другого подхода. Детали здесь: https://wiki.python.org/moin/WindowsCompilers

    Остальное — оч-ч-чень интересно, надо пробовать и разбираться в деталях.


  1. sshikov
    16.08.2016 18:55
    +1

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

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


    1. eyeofhell
      17.08.2016 07:36

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


      1. sshikov
        17.08.2016 09:40
        +1

        Ну если по-простому — то почти у всех языков на платформе 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.*


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


        1. Grab
          17.08.2016 21:10
          +2

          Пришла оповещалка о том, что кто-то меня упомянул — значит опять про Grapes пишут :)


  1. Mayflower
    16.08.2016 21:25

    Как правило, создатели нового языка программирования уделяют этому не очень много внимания… Единственным на моей памяти исключением является node.js

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


    1. ozkriff
      17.08.2016 11:04

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


  1. Fedcomp
    16.08.2016 23:51

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


    1. ozkriff
      17.08.2016 11:02
      +1

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


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


  1. ozkriff
    17.08.2016 10:56
    +1

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

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


  1. vladshulkevich
    17.08.2016 14:01
    +3

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

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

    Понимаете, не тривиальное это дело, собранное колесо поставить. А вы говорите зависимости.


    1. Meklon
      17.08.2016 15:20

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


      1. vladshulkevich
        17.08.2016 16:27

        винда у проверяющего


        1. Meklon
          17.08.2016 16:41
          +1

          Блин. Забываю уже. Привык к Линуксу за последние годы.


      1. iroln
        17.08.2016 16:28

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


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


        pip install numpy

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

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


        1. Meklon
          17.08.2016 16:41

          Насчет старой версии согласен, но субъективно, далеко не всегда bleeding edge нужен. По крайней мере, я редко с таким сталкивался.


        1. dimm_ddr
          17.08.2016 23:45

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


          1. iroln
            17.08.2016 23:50

            Я выше пишу:


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

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


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


            1. dimm_ddr
              18.08.2016 10:22

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


        1. nikolay_karelin
          19.08.2016 13:54

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


  1. vladkens
    20.08.2016 12:11

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

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

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


    1. nikolay_karelin
      21.08.2016 21:48

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


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