System administration
Python
DevOps
November 2018 14

xonsh — python как замена shell

Удивительно, на на хабре до сих пор нет поста о такой, весьма интересной, замене шеллу как xonsh (github), с моей точки зрения синтаксис всяких shell'ов ужасен и не вижу никаких оснований сохранять его в 21 веке, а Python, в свою очередь, обладает прекрасным синтаксисом и массой других преимуществ, поэтому, на мой взгляд, он и должен быть языком автоматизации по умолчанию, чего и пытаеся достичь xonsh.


Какое-то время использую xonsh, поэтому думаю, что могу рассказать о нём достаточно для того, чтобы начать пользоваться.


Оговорки:


  • xonsh это только про Python 3, но это норма.
  • xonsh ещё не релизнулся (версия 0.8.3 на момент написания), видимо по мнению разработчиков ещё не все желаемые фичи реализованы, но по моим ощущениям всё работает (если разобраться с отличиями, о чём ниже).

Основная особенность xonsh в том, что он "магически" угадывает что вы ввели — команду питона или шелла, и это работает вполне хорошо.


Вставлять питонные код в команды шелла можно с помощью собаки.


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


worldmind@x ~ $ for i in range(3): 
...............     echo $SHELL 

Поэтому я постараюсь сосредоточиться на том, что не описано или описано плохо.


Установка


Я буду описывать установку (для Debian/Ubuntu) не требующую права суперпользователя, хотя я только недавно перешёл на такую схему, раньше я ставил в системные папки, прописывал его в /etc/shells и менял шелл командой chsh, но на первый взгляд всё работает также и при новом способе и он мне кажется более правильным, не хочется засорять систему пакетами не из репозиториев, но тут каждый решает для себя сам.


Ставим pip если ещё не:


sudo apt-get install python3-pip

Ставим xonsh (без sudo), я привожу команду которая устанавливает все опциональные зависимости, чтобы получить все плюшки задуманные авторами, если кто-то хочет минимальную установку, то можно удалить квадратные скобки с содержимым:


pip3 install --user xonsh[ptk,pygments,proctitle,linux]

Скорее всего у вас уже, где-нибудь в .profile в PATH добавляются пути к локальной папке с бинарниками $HOME/.local/bin, но они добавляются только при их наличии, поэтому нужно перезапустить терминал, чтобы этот код отработал и бинарник xonsh можно было запустить и посмотреть.
Обновление стандартно:


pip3 install --user xonsh --upgrade

venv


Ставим venv если хотим пользоваться соответствующим функционалом (см. далее про vox):


sudo apt-get install python3-venv

Всякие venv заточены под конкретные шеллы, поэтому xonsh предлагает свою обёртку называемую vox, но для комфортного использования стоит устанавливать расширение avox:


pip3 install --user xontrib-avox

Установка pyenv


Если есть необходимость в виртуальных окружениях с произвольной версией питона, то нужно склонировать pyenv предварительно установив зависимости для сборки питона:


git clone https://github.com/pyenv/pyenv.git ~/.pyenv

Далее в примере конфига можно узреть установку пары переменных окружения для использования pyenv.


Запуск


Теперь у нас всё установлено и осталось сделать xonsh шеллом, для того, чтобы не менять ничего вне юзерской папки я использую следующий код (по мотивам SO) для баша (если у вас другой шелл, то вы знаете что делать, но не используйте .profile т.к. xonsh его тоже читает) добавленный в .bashrc:


# set default shell without editing /etc/shells
if [ "${XONSH_VERSION:-unset}" = "unset" ] ; then
    export SHELL=$HOME/.local/bin/xonsh
    exec $HOME/.local/bin/xonsh -l
fi

Перезапускаем шелл и, если всё прошло удачно, вы уже в xonsh т.е. по сути в питон консоли и можете например производить вычисления прямо в командной строке, например узнать сколько будет 2+2.


Настройка


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


aliases['g'] = 'git'

import os
local_bin = '{}/.local/bin'.format($HOME)
if os.path.isdir(local_bin):
    $PATH.append(local_bin)

$PYENV_ROOT = '%s/.pyenv' % $HOME
$PATH.insert(0, '%s/bin' % $PYENV_ROOT)

xontrib load vox
$PROJECT_DIRS = ["~/projects"]
xontrib load avox

Перезапускам шелл для применения новых настроек.


Стоит обратить внимание на человеческую модель данных — алиасы это словарь, пути это список, вроде очевидно, но почему-то не всегда оно так.
Также, мы в конфиге импортировали модуль os это значит что он уже будет доступен в нашем шелле, таким образом можно наимпортить нужных модулей и получить своё, удобное окружение.


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


Использование виртуальных окружений


Создаём папку проекта (avox ожидает что все проекты лежат в $PROJECT_DIRS):


mkdir -p projects/test

Создаём виртуальное окружение для этого проекта:


vox new test

Благодаря настроенному дополнению avox нам достаточно перейти в папку проекта чтобы активировать виртуальное окружение, никаких странных source ./bin/activate выполнять не нужно:


worldmind@x ~ $ cd projects/test/
(test) worldmind@x ~/projects/test $ pip install see
...
(test) worldmind@x ~/projects/test $ python -c 'import see'

По выходу из папки виртуальное окружение деактивируется:


(test) worldmind@x ~/projects/test $ cd
worldmind@x ~ $ python3 -c 'import see' err>out | fgrep 'NotFound'
ModuleNotFoundError: No module named 'see'

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


Для полноты картины хотело бы, чтобы в этих виртуальных окружениях можно было бы использовать произвольную версию питона, например установленную через pyenv, но пока не срослось, а самому подкостылить руки не дошли.
UPD: Не так давно xonsh научили использовать произвольную версию питона в виртуальных окружениях.
Устанавливаем желаемую версию питона (список доступных pyenv install --list):


pyenv install 3.7.2

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


mkdir projects/projectwith3.7
vox new -p $PYENV_ROOT/versions/3.7.2/bin/python projectwith3.7

Проверяем:


(projectwith3.7) worldmind@x ~/projects/projectwith3.7 $ python --version
Python 3.7.2

Грабли


Единственное на что я накнулся это отличия в эскейпинге:


find . -name data.txt -exec echo {} \;

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


find . -name .xonshrc -exec echo '{}' ';'

некоторые отличия от bash есть в виде таблицы в документации.


Вывод


Мне кажется, что xonsh это хорошой претендент на нормальный шелл будущего для всех, а особенно он должен понравиться питонистам. Начните пользоваться (установка без sudo упрощает откат назад, можно просто удалить папку), чтобы понять всё ли там есть лично для вас, может это то, что вы искали, но боялись установить.

+20
13.2k 91
Comments 92
Top of the day