Сяброўваем Python і Bash: бібліятэкі smart-env і python-shell

Добрага часу сутак усім.

На сённяшні дзень Python з'яўляецца адной з найболей выкарыстоўваных моў у сферы стварэння не толькі непасрэдна праграмных прадуктаў, але таксама забеспячэнні іх інфраструктуры. З прычыны гэтага шматлікім дэвапсам, па іх волі ці супраць гэтай, прыйшлося вучыць новую мову для наступнага выкарыстання ў якасці дадатку да старых добрых Bash-скрыптаў. Аднак Bash і Python вызнаюць розныя падыходы да напісання кода і маюць пэўныя асаблівасці, на ўвазе чаго партаванне Bash-скрыптоў на "змяіную мову" часам аказваецца ёмістай і далёка не трывіяльнай задачай.

Каб спрасціць жыццё дэвапсам, створана і працягвае стварацца шмат карысных бібліятэк і ўтыліт на Python. Гэты артыкул апісвае адразу дзве новыя бібліятэкі, створаныя аўтарам гэтай пасады. smart-env и python-shell - і закліканыя пазбавіць дэвопса ад неабходнасці надаваць шмат увагі тонкасцям працы з Python, пакідаючы прастор для цікавейшых задач. Сфера дзейнасці бібліятэк - зменныя асяроддзі і запуск знешніх утыліт.

Каго зацікавіла, прашу пад кат.

Новыя «ровары»?

Здавалася б, навошта ствараць новыя пакеты для дастаткова звычайных аперацый? Што мяшае выкарыстоўваць напроста os.environ і subprocess.<метад або клас на ваш густ>?

Доказы на карысць кожнай з бібліятэк прывяду асобна.

Бібліятэка smart-env

Перад тым, як пісаць уласнае стварэнне, карысна палезці ў Інтэрнэт і пашукаць гатовыя рашэнні. Вядома, ёсць рызыка не знайсці тое, што трэба, але гэта, хутчэй, "страхавы выпадак". Як правіла, падыход спрацоўвае і эканоміць кучу часу і сіл.

па выніках пошуку было выяўлена наступнае:

  • ёсць пакеты, сапраўды якія абгортваюць выклікі да os.environ, аднак пры гэтым патрабавальныя кучу адцягваючых дзеянняў (стварэнне асобніка класа, спец-параметры ў выкліках і інш.);
  • ёсць нядрэнныя пакеты, якія, аднак, цвёрда завязаныя на пэўную экасістэму (у асноўным, на вэб-фрэймворкі накшталт Django) і таму без напільніка зусім не ўніверсальныя;
  • ёсць рэдкія спробы зрабіць нешта новае. Напрыклад, дадаць тыпізацыю і відавочна парсіць значэння зменных шляхам выкліку метадаў выгляду
    get_<typename>(var_name)

    Або вось яшчэ адно рашэнне, якое, аднак, не падтрымлівае цяпер гнаны Python 2 (на якім, нягледзячы на афіцыйны RIP, усё яшчэ застаюцца горы напісанага кода і цэлыя экасістэмы);

  • ёсць школьна-студэнцкія вырабы, наогул незразумела навошта якія апынуліся ў апстрымным PyPI і толькі што ствараюць праблемы з найменнем новых пакетаў (у прыватнасці, назва "smart-env" - змушаная мера).

І гэты спіс можна працягваць доўга. Аднак і прыведзеных вышэй пунктаў хапіла, каб загарэцца ідэяй зрабіць нешта зручнае і ўніверсальнае.

Патрабаванні, якія ставіліся перад напісаннем smart-env:

  • Максімальна простая схема выкарыстання
  • Лёгка канфігуруемая падтрымка тыпізацыі дадзеных
  • Сумяшчальнасць з Python 2.7
  • Добрае пакрыццё кода тэстамі

У канчатковым выніку, усё гэта ўдалося рэалізаваць. Вось прыклад выкарыстання:

from smart_env import ENV

print(ENV.HOME)  # Equals print(os.environ['HOME'])

# assuming you set env variable MYVAR to "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Equals boolean True

ENV.NEW_VAR = 100  # Sets a new environment variable

Як відаць з прыкладу, для працы з новым класам дастаткова яго імпартаваць (ствараць асобнік не трэба - мінус лішняе дзеянне). Доступ да любой зменнай асяроддзі дасягаецца шляхам звароту да яе як да зменнай класа ENV, што, фактычна, робіць гэты клас інтуітыўна зразумелай абгорткай натыўнага сістэмнага асяроддзя, раўналежна ператвараючы яго ў магчымы варыянт аб'екта канфігурацыі практычна любой сістэмы (падобны падыход, напрыклад, дасягаецца ў Django , толькі там канфігурацыйным аб'ектам выступае непасрэдна модуль/пакет settings).

Уключэнне/выключэнне рэжыму падтрымкі аўтаматычнай тыпізацыі дасягаецца выкарыстаннем двух метадаў - enable_automatic_type_cast() і disable_automatic_type_cast(). Гэта можа быць зручна, калі ў зменнай асяроддзі ляжыць серыялізаваны JSON-падобны аб'ект ці нават проста булевая канстанта (яўнае прапісванне зменнай DEBUG у Django шляхам параўнання зменнай асяроддзі з "дапушчальнымі" радкамі - адзін з часта сустракаемых выпадкаў). Але цяпер няма патрэбы відавочна канвертаваць радкі - большая частка неабходных дзеянняў ужо закладзена ў нетрах бібліятэкі і толькі чакае сігналу да дзеяння. 🙂 У цэлым жа тыпізацыя працуе празрыста і падтрымлівае амаль усе наяўныя ўбудаваныя тыпы дадзеных (не тэсціравалі frozenset, complex і bytes).

Патрабаванне падтрымкі Python 2 было рэалізавана практычна без ахвяр (адмова ад typing і некаторых «цукровых цукерак» апошніх версій Python 3), у прыватнасці, дзякуючы ўсюдыіснага six (для рашэння праблем выкарыстання метакласаў).

Але ёсць і крыху абмежаванняў:

  • Падтрымка Python 3 мае на ўвазе версію 3.5 і вышэй (іх наяўнасць у вашым праекце – вынік альбо ляноты, альбо адсутнасці неабходнасці ў паляпшэннях, бо складана прыдумаць аб'ектыўную прычыну, чаму вы да гэтага часу сядзіце на 3.4);
  • У Python 2.7 бібліятэка не падтрымлівае дэсерыялізацыю літаралаў мностваў. Апісанне тут. Але, калі хто-небудзь захоча рэалізаваць - welcome:);

Бібліятэка таксама вызнае механізм выключэнняў на выпадак памылак парсінгу. Калі радок не атрымалася распазнаць ніводным з наяўных аналізатараў, значэнне застаецца радковым (хутчэй, з меркаванняў выгоды і зваротнай сумяшчальнасці з звыклай логікай працы зменных у Bash).

Бібліятэка python-shell

Зараз раскажу пра другую бібліятэку (апісанне недахопаў наяўных аналагаў апушчу — яно падобна на апісанае для smart-env. Аналогі — тут и тут).

У цэлым, ідэя рэалізацыі і патрабаванні да яе аналагічныя апісаным для smart-env, што відаць з прыкладу:

from python_shell import Shell

Shell.ls('-l', '$HOME')  # Equals "ls -l $HOME"

command = Shell.whoami()  # Equals "whoami"
print(command.output)  # prints your current user name

print(command.command)  # prints "whoami"
print(command.return_code)  # prints "0"
print(command.arguments)  # prints ""

Shell.mkdir('-p', '/tmp/new_folder')  # makes a new folder

Ідэя такая:

  1. Адзіны клас, які ўвасабляе Bash у свеце Python;
  2. Кожная Bash-каманда выклікаецца як функцыя класа Shell;
  3. Параметры выкліку кожнай функцыі далей пракідваюцца ў выклік адпаведнай каманды Bash;
  4. Кожная каманда выконваецца "тут і цяпер" у момант яе выкліку, г.зн. працуе сінхронны падыход;
  5. ёсць магчымасць атрымаць доступ да выхлапу каманды ў stdout, а таксама код яе звароту;
  6. Калі каманда адсутнічае ў сістэме - кідаецца выключэнне.

Як і ў выпадку са smart-env, забяспечана падтрымка Python 2 (праўда, ахвярнай крыві спатрэбілася крыху больш) і адсутнічае падтрымка Python 3.0-3.4.

Планы па развіццю бібліятэк

Выкарыстоўваць бібліятэкі можна ўжо зараз: абедзве выкладзены на афіцыйны PyPI. Зыходнікі даступныя на Github (гл. ніжэй).

Абедзве бібліятэкі будуць развівацца з улікам фідбэка, сабранага ад зацікаўленых. І, калі ў smart-env, можа, і складана прыдумаць разнастайнасць новых фіч, то ў python-shell сапраўды ёсць яшчэ што дадаць:

  • падтрымка неблакіруючых выклікаў;
  • магчымасць інтэрактыўных зносін з камандай (праца з stdin);
  • даданне новых уласцівасцяў (напрыклад, property для атрымання выхлапу са stderr);
  • рэалізацыя каталога даступных каманд (для выкарыстання з функцыяй dir());
  • і г.д.

Спасылкі

  1. Бібліятэка smart-env: Github и PyPI
  2. Бібліятэка python-shell: Github и PyPI
  3. Тэлеграм-канал абнаўленняў бібліятэк

UPD 23.02.2020:
* Рэпазітары перанесены, адпаведныя спасылкі абноўлены
* Версія python-shell==1.0.1 рыхтуецца да выхаду 29.02.2020. Сярод змен - падтрымка аўтакампліты каманд і каманды dir(Shell), запуск каманд з Python-невалідным ідэнтыфікатарам, выпраўленне багаў.

Крыніца: habr.com

Дадаць каментар