Пишемо shell скрипти на python і чи можна замінити їм bash

Пишемо shell скрипти на Python і чи можна замінити їм Bash +36

  • 21.02.16 2:31 •
  • lamerman •
  • # 277679 •
  • Хабрахабр •
  • 34 •
  • 26400

- такий же як Forbes, тільки краще.

У цій невеликій статті мова піде про те, чи можна легко використовувати Python для написання скриптів замість Bash / Sh. Перше питання, яке виникне у читача, мабуть, а чому, власне, не використовувати Bash / Sh, які спеціально були для цього створені? Створені вони були досить давно і, на мій погляд, мають досить специфічний синтаксис, не сильно схожий на інші мови, який досить складно запам'ятати, якщо ви не адміністратор 50+ лівіла. Пам'ятайте, ви навскидку як написати на ньому простий if?


Елементарно правда? Інтуїтивно зрозумілий синтаксис. )

Проте в python ці конструкції набагато простіше. Кожен раз коли я пишу що то на баші, то неодмінно лізу в поисковик щоб згадати як писати простий if, switch або щось ще. Присвоєння я вже запам'ятав. ) В Python все інакше. Я хоч і не пишу на ньому цілодобово, але ніколи не доводилося лізти і дивитися як там зробити простий цикл, тому що синтаксис мови простий і інтуїтивний. Плюс до всього він набагато ближче до решти мейнстрімовим мов типу java або c ++, ніж Bash / Sh.

Також в стандартній та інших бібліотеках Python є набагато більш зручні бібліотеки ніж консольні утиліти. Скажімо, ви хочете розпарсити json, xml, yaml. Знаєте який я недавно бачив код в БАШЕЄВ щоб зробити це? правильно:


І це був не мій код. Це був код БАШЕЄВ / пітон нейтральну людину.

Те ж саме з регексом, sed безперечно зручна утиліта, але як багато людей пам'ятає як правильно її використовувати? Ну крім Lee E. McMahon, який її створив. Так впринципі багато хто пам'ятає, навіть я пам'ятаю як робити прості речі. Але, на мій погляд, в Python модуль re набагато зручніше.

У цій невеликій статті я хотів би представити вам діалект Python який називається shellpy і служить для того, щоб наскільки це можливо замінити Bash на python в скриптах.


Shell python нічим не відрізняється від простого Python крім однієї деталі. Вирази всередині grave accent символів ( `) на відміну від Python не є eval, а позначає виконання команди в короби. наприклад


виконає ls -l як shell команду. Також можливо написати все це без `в кінці рядка


і це теж буде коректним синтаксисом.

Можна виконувати відразу кілька команд на різних рядках


і команди, що займають кілька рядків


Виконання кожного виразу в shellpy повертається об'єкт класу Result


Це можна бути або Result або InteractiveResult (Посилання на гітхаб з документацією, можна і потім подивитися :)). Давайте почнемо з простого результату. З нього можна легко отримати код повернення виконаної команди


І текст з stdout і stderr


Можна також пробігтися по всіх рядках stdout виконаної команди в циклі

Для результату є також ще дуже багато синтаксичного цукру. Наприклад, ми можемо легко перевірити, що код повернення виконуваної команди дорівнює нулю


Або ж більш простим способом отримати текст з stdout


Все перераховане вище - це огляд синтаксису коротко, щоб просто зрозуміти основну ідею і не вантажити вас усіма-усіма деталями. Там є ще багато чого і для інтерактивної взаємодії з виконуваними командами, для управління виконанням команд. Але це все деталі, в які можна зануритися в документації (англійською мовою), якщо сама ідея вам здасться цікавою.

Це ж не дійсний синтаксис Python виходить, як все працює то?


Магія звичайно, як ще :) Так, друзі мої, мені довелося використовувати препроцессінг, каюсь, але іншого способу я не знайшов. Я бачив інші бібліотеки, які роблять щось подібне, не порушуючи синтаксису мови на кшталт

Знайомий з темою читач запитає, чим IPython то тебе не влаштував, там ж майже як у тебе тільки значок інший ставити треба, може ти просто велосипедист, якому ліньки зазирнути в пошуковик? І правда він виглядає ось так:


Я його намагався використовувати але зустрів пару серйозних проблем, з якими ужитися не зміг. Найголовніша з них, то що немає простого імпорту як в Python. Тобто ти не можеш написати якийсь код на самому ipython і легко його перевикористати в інших місцях. Неможливо написати для свого ipython модуля


і щоб все відразу запрацювало як в казці. Єдиний спосіб перевикористати скрипт, це виконати його. Після виконання в оточенні у тебе з'являються всі функції і змінні, оголошені в виконуваному файлі. Чи не кошерно на мій погляд.

У shellpy код переіспользуется легко і імпортується точно так само як і в звичайному python. Припустимо у нас є модуль common в якому ми зберігаємо дуже корисний код. Заглянемо в директорію з цим модулем


Отже, що у нас тут є, ну по перше init. але з розширенням .spy. Це і є відмінною рисою spy модуля від звичайного. Подивимося також всередину файлу common.spy, що там цікавого


Ми бачимо що тут оголошена функція, яка всередині себе використовує shellpy синтаксис щоб повернути результат виконання `echo 5. Як цей модуль використовується в коді? А ось як


Бачите? Як в звичайному Python, просто взяли і заімпортіровалі.

Як же все працює. Це працює за допомогою PEP 0302 - New Import Hooks. Коли ви імпортуєте щось в своєму коді то спочатку Python запитує у хука, чи немає тут чогось свого, хук переглядає PYTHONPATH на наявність файлів * .spy або модулів shellpython. Якщо нічого немає, то так і каже: "Нічого немає, імпортує сам". Якщо ж він знаходить щось там, то хук займається імпортом самостійно. А саме, він робить препроцессінг файлу в звичайний python і складає все це добро в temp директорію операційної системи. Записавши новий Python файл або модуль він додає його в PYTHONPATH і за справу береться вже звичайнісінький імпорт.

Давайте ж скоріше подивимося на який-небудь приклад


Shellpython можна встановити двома способами: pip install shellpy або склоніровав репозиторій і виконавши setup.py install. Після цього у вас з'явиться утиліта shellpy.

Запустимо ж що-небудь


Після установки можна потестувати shellpython на прикладах, які доступні прямо в репозиторії.


Також тут є allinone приклади, які називаються так, тому що тестують все-все функції, які є в shellpy. Загляньте туди, щоб краще пізнати що ж там ще такого є, або просто виконайте


Для третього Python команда виглядає ось так

сумісність


Це працює на Linux і має працювати на Mac для Python 2.x і 3.x. На віндовсі поки не працює, але проблем ніяких для роботи немає, так як все писалося з використанням кроссплатформенних бібліотек і нічого платформоспеціфічного в коді немає. Просто не дійшли руки ще, щоб потестувати на віндовсі. Мака у мене теж немає, але начебто у одного працювало :) Якщо у вас є мак і у вас все нормально, скажіть будь ласка.

Документація (англійською)

Чи можна законтрібьютіть

Воно мені нічого в продакшені НЕ розламає?


Зараз версія 0.4.0, це не Стейбл і продакшн процеси поки краще не зав'язувати на скрипт, почекавши поки все налагодити. Але в девелопменті, CI можна використовувати цілком. Все це покрито тестами і працює :)


Пишіть ваші відгуки про ідею в цілому і про реалізацію зокрема, а також про проблеми, побажання, всіх радий почути :) Заводите Issues ще в гітхабе, там їх вже багато :)

Я дуже довго жив на bash і тільки в минулому році вирішив знову поекспериментувати з цими новомодними оточеннями. zsh вирішив пропустити, а почав з xonsh, так як здавалося, що це може бути зручно. Загалом, не ужився я з ним через дивацтв (автодоповнення мені весь час заважало зрозуміти що ж я пишу) і відсутності досить базових речей на зразок і || в bash. ну і підтримка virtualenv крива (і це в shell'e на Python для любителів писати проекти на Python). А ось fish - дійсно виявився дуже приємною штукою, тут і зупинився (навіть невеликий скрінкасти записав).

Буквально тиждень тому додав в xonsh менеджер оточень :-) Є, що поліпшити, але в цілому проблема вирішена.

Проекту є, куди рости, не сперечаюся.

якісь спірні пункти в порівнянні, у fish нормальна історія, і з стандартнорй бібліотекою теж все норм, вже рік використовую, дуже задоволений, особливо гітом з коробки і плагіном для віртуаленв. Може просветите з приводу цих пунктів?

Не завжди все так жахливо в bash, можна використовувати звичайні оператори порівняння, замість -ne та інших.
Самому сподобалося використовувати в пітон argparse, для консольних команд. А його вже викликати bash скриптом наприклад.

Мені подобається. Имхо, в першу чергу треба подумати в сторону реалізації / реюза readline для такого шелла. Знову ж имхо - якщо основний юзекейс скрипти, то шансів злетіти набагато менше, без зручного інтерактивного режиму в сенсі.

ви хочете розпарсити json, xml, yaml Є jq / xmlstarlet / shyaml. то неодмінно лізу в поисковик Замість того, щоб в мануал глянути, який вже на диску лежить. Зазвичай. синтаксис мови простий і інтуїтивний У шей він теж простий і інтуїтивний, якщо допереть, що «ключові слова» - це насправді імена команд, відповідно, вони завжди стоять на початку і не більше одного на команду. А так-то у пихтона в порівнянні з «мейнстрімними мовами» синтаксис не менше дивний. І прив'язка синтаксису до форматування багатьох відлякує. Іноді красивіше однострочнікі написати, ніж довгу вузеньку «сходи».

Є jq / xmlstarlet / shyaml
Мова не про те, що щось є в принципі, а про зручність використання.

Замість того, щоб в мануал глянути, який вже на диску лежить. Зазвичай.
Навіщо лізти в мануал для того щоб подивитися синтаксис одного оператора (будь ласка, не спитайте це з "навіщо взагалі лізти в мануал", я цього не говорив :))? Пошуковик дасть відповідь миттєво, а мануал треба спочатку знайти, потім в ньому знайти if.

а про зручність використання Ну і чим впіхіваніе в однострочнікі скриптів на іншій мові зручніше розрахованих на CLI утиліт з компактним синтаксисом запитів? Пошуковик дасть відповідь миттєво Якщо з'єднання швидке. І навіть при цьому треба перегорнути пару-трійку сайтів. мануал треба спочатку знайти Прям так складно man bash набрати, ага. потім в ньому знайти if. А ось з цим там проблема, так, дюжеть великий мануал, і колізій на пошук багато, навіть під / ^ \ s + if багато підпадає. З іншого боку, якщо перегорнути його разок весь, то можна запам'ятати, що команди в кінці.

awk - взагалі окрема мова з купою фич. На ньому цілком досить великі скрипти пишуть. Ну і sed - не промах, крім попсового s / foo / bar / там ще купа корисних можливостей, з самого простого - друк певного діапазону рядків (sed -n 17,19p). А ще теоретично на ньому можна реалізувати будь-яка нормальна алгоритм Маркова, але це вже з розряду збочень.