Удивительно, на на хабре до сих пор нет поста о такой, весьма интересной, замене шеллу как 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 упрощает откат назад, можно просто удалить папку), чтобы понять всё ли там есть личн�� для вас, может это то, что вы искали, но боялись установить.


Дополнения в комментариях


  1. Установка переменных окружения для папок.
  2. Хуки на активацию виртуального окружения