Подборка полезных библиотек на Python #1

@, в [Python]

Уже давно существует мега-подборка питоновских батареек на любой вкус и цвет: awesome-python. Приходится её парсить и вытаскивать оттуда подмножество батареек с нужным вкусом и цветом.

attrs: классы без шаблонного кода

Ссылка. Смысл библиотеки в том, чтобы избавить юзера от необходимости описывать тупой код типа копирования атрибутов, сравнения классов, __repr__, __str__, и т.д. Несколько примеров для оценки полезности.

1
2
3
4
@attr.s
class SmartClass(object):
   a = attr.ib()
   b = attr.ib()

Полностью эквивалентно:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class ArtisanalClass(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        
    def __repr__(self):
        return "ArtisanalClass(a={}, b={})".format(self.a, self.b)
    
    def __eq__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) == (other.a, other.b)
        else:
            return NotImplemented
        
    def __ne__(self, other):
        result = self.__eq__(other)
        if result is NotImplemented:
            return NotImplemented
        else:
            return not result
        
    def __lt__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) < (other.a, other.b)
        else:
            return NotImplemented
        
    def __le__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) <= (other.a, other.b)
        else:
            return NotImplemented
        
    def __gt__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) > (other.a, other.b)
        else:
            return NotImplemented
        
    def __ge__(self, other):
        if other.__class__ is self.__class__:
            return (self.a, self.b) >= (other.a, other.b)
        else:
            return NotImplemented
        
    def __hash__(self):
        return hash((self.a, self.b))

Ещё в attrs есть куча плюшек, например, Immutability, автоматические PEP526 атрибуты для Python3.6+, валидаторы атрибутов, автоматическое создание слотов (__slots__ для экономии памяти/ускорения, [1], [2], [3]), и т.д. Больше всего мне, конечно нравится PEP526 атрибуты:

import typing
@attr.s(auto_attribs=True)
class AutoC:
    cls_var: typing.ClassVar[int] = 5  # this one is ignored
    l: typing.List[int] = attr.Factory(list)
    x: int = 1
    foo: str = attr.ib(
         default="every attrib needs a type if auto_attribs=True"
    )
    bar: typing.Any = None

MonkeyType

Библиотека за авторством Instagram для автоматического создания аннотаций (тайп-хинтов) к коду. Хорошие тесты позволят нагенерить stub'ов и вставить в код аннотации. Типы берутся из рантайма.

monkeytype run `which pytest`

При запуске создаёт файлик monkeytype.sqlite3 такого вида:

CREATE TABLE monkeytype_call_traces 
  ( 
     created_at  TEXT, 
     module      TEXT, 
     qualname    TEXT, 
     arg_types   TEXT, 
     return_type TEXT, 
     yield_type  TEXT 
  )

И складывает туда то, что удалось выдрать профайлером из рантайма.

# показать что там нагенерило в stdout
monkeytype stub mymodule.utils
# применить то что нагенерило
monkeytype apply mymodule.utils

Стоит заметить, что при наличии частично указанных типов ведёт себя странно и часто падает. Что печально.

Есть еще аналогичная библиотека за авторством Dropbox - pyannotate. И плагин для pytest. Отличительная черта - поддержка PEP484 и Python27. Аннотации выглядят примерно так:

def embezzle(self, account, funds=1000000, *fake_receipts):
    # type: (str, int, *str) -> None
    """Embezzle funds from account using fake receipts."""

pipreqs

Батарейка для автоматической генерации requirements.txt по использованным импортам. Лучше чем pip freeze тем, что не цепляет зависимости сторонних пакетов.

furl

Библиотека для простой работы с url'ами.

from furl import furl
f = furl('http://www.google.com/?one=1&two=2')
f.args['three'] = '3'
del f.args['one']
print(f.url)
'http://www.google.com/?two=2&three=3'
# ========
f.set(host=u'ドメイン.テスト', path=u'джк', query=u'☃=☺')
f.url
f.url == 'http://xn--eckwd4c7c.xn--zckzah/%D0%B4%D0%B6%D0%BA?%E2%98%83=%E2%98%BA'

fire

Библиотека за неофициальным авторством гугла для превращения всего в огонь позволяет прицепить CLI к любому объекту. 

import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)
python calculator.py double 10  # 20
python calculator.py double --number=15  # 30

python-phonenumbers

Порт гугловской libphonenumber. Для указанного телефонного номера позволяет определить страну, проверить валидность номера, получить локальный номер, вытащить из строки потенциальные номера и т.д. Полезная штука, в общем.

phonenumbers.parse('+79251234567')
PhoneNumber(
  	country_code=7, 
  	national_number=9251234567, 
  	extension=None, 
  	italian_leading_zero=None, 
  	number_of_leading_zeros=None, 
  	country_code_source=0, 
  	preferred_domestic_carrier_code=None
)
# также можно указывать номера в локальном формате:
x = phonenumbers.parse('9251234567', region='RU')
# можно привести к e164 формату:
x = phonenumbers.parse('9251234567', region='RU')
phonenumbers.format_number(x, phonenumbers.PhoneNumberFormat.E164)
'+79251234567'

sh - обёртка для subprocess

Библиотека реализует реально простой интерфейс для вызова консольных команд.

# индентично ls -lah | grep READ
sh.grep(sh.ls('-lah'), 'READ')
'-rw-r--r--  1 user user 3,8K дек 29 17:51 README.md'
# ls -lah | grep -i read
sh.grep(sh.ls('-lah'), '-i', 'read')
'-rw-r--r--  1 user user 3,8K дек 29 17:51 README.md'

# выполнение команд в фоне
res = sh.grep(sh.ls('-lah'), '-i', 'read', _bg=True)
sh.which('python')
'/home/user/.pyenv/versions/3.6.4/envs/work/bin/python'
res.wait()
'-rw-r--r--  1 user user 3,8K дек 29 17:51 README.md'
night-crawler
Просмотров: 214
blog comments powered by Disqus