понедельник, 22 октября 2012 г.

psh - библиотека для запуска процессов (Python)

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

Все свои скрипты и программы я всегда пишу со здравым уровнем паранои, поэтому каждый раз, когда вижу конструкции вида `grep word some_file | wc -l`, мне всегда хочется не только получить вывод `wc -l`, но и проверить, завершился ли нормально grep (вдруг он, к примеру, не смог открыть файл). Делать это каждый раз вручную в shell быстро надоест, а в Python есть исключения, которые как раз могут тут очень помочь.

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

Получился вот такой модуль - psh. Даже не поленился написать к нему документацию. Буду рад, если он пригодится не только мне. :)

Пример использования для затравки:
"""
Check free disk space on remote host myserver.com

Output:
    /dev/sda1 (/) ran out of disk space (86%)
    /dev/sda2 (/mnt/data) ran out of disk space (95%)
"""

import re
from psh import sh

# ssh myserver.com 'df | egrep "^/dev/"'
with sh.ssh("myserver.com", sh.df() | sh.egrep("^/dev/"), _shell = True) as ssh:
    for line in ssh:
        match = re.search(r"^(/dev/[^\s]+)\s+(?:[^\s]+\s+){3}(\d+)%\s+(/.*)$", line.rstrip("\n"))
        device, used, mount_point = match.groups()
        if int(used) > 80:
            print "{0} ({1}) ran out of disk space ({2}%)".format(device, mount_point, used)

2 комментария:

Анонимный комментирует...

Посмотрите библиотеку pbs. Тоже достойная вещь.

Dmitry Konishchev комментирует...

pbs - это предок sh, на который я как раз и смотрел. ;)