Главная » Хабрахабр » Подборка @pythonetc, декабрь 2018

Подборка @pythonetc, декабрь 2018

Это седьмая подборка советов про Python и программирование из моего авторского канала @pythonetc.

Предыдущие подборки:

Множественные контексты

Иногда бывает нужно запустить какой-то блок кода в нескольких менеджерах контекста:

with open('f') as f: with open('g') as g: with open('h') as h: pass

Со времён Python 2.7 и 3.1 это можно сделать с помощью одного выражения:

o = open
with o('f') as f, o('g') as g, o('h') as h: pass

А раньше можно было воспользоваться функцией contextlib.nested:

with nested(o('f'), o('g'), o('h')) as (f, g, h): pass

Если вы работаете с неопределённым количеством менеджеров контекста, то лучше выбрать более продвинутые инструменты. contextlib.ExitStack позволяет в любое время входить в любое количество контекстов и гарантирует выход из них по окончании исполнения:

with ExitStack() as stack: f = stack.enter_context(o('f')) g = stack.enter_context(o('g')) other = [ stack.enter_context(o(filename)) for filename in filenames ]

Объекты в памяти интерпретатора

Ко всем объектам, которые в данный момент находятся в памяти интерпретатора, можно получить доступ с помощью gc.get_objects():

In : class A:
...: def __init__(self, x):
...: self._x = x
...:
...: def __repr__(self):
...: class_name = type(self).__name__
...: x = self._x
...: return f'({x!r})'
...: In : A(1)
Out: A(1) In : A(2)
Out: A(2) In : A(3)
Out: A(3) In : [x for x in gc.get_objects() if isinstance(x, A)] Out: [A(1), A(2), A(3)]

Символы-цифры

In : int('୧৬༣')
Out: 163

0 1 2 3 4 5 6 7 8 9 — это не единственные символы, считающиеся цифрами. Python соблюдает правила Unicode и считает цифрами несколько сотен символов. Полный список здесь.

Это имеет значение для функций вроде int, unicode.isdecimal и даже re.match:

In : int('௯')
Out: 9 In : '٢'.isdecimal()
Out: True In : bool(re.match('\d', '౫'))
Out: True

Полночь по UTC

>>> bool(datetime(2018, 1, 1).time())
False
>>> bool(datetime(2018, 1, 1, 13, 12, 11).time())
True

До Pyhon 3.5 объекты datetime.time() считались ложными, если они представляли полночь по UTC. Это может приводить к неочевидным багам. В следующем примере if not может не выполниться не потому, что create_time
является None, а потому что это полночь.

def create(created_time=None) -> None: if not created_time: created_time = datetime.now().time()

Обойти этот баг можно с помощью явной проверки на None: if created_time is None.

Асинхронная работа в ФС

Python не поддерживает асинхронные операции с файлами. Чтобы сделать их неблокирующими, приходится использовать треды.

Для асинхронного исполнения кода в потоке нужно использовать метод loop.run_in_executor.

За вас это может сделать сторонний модуль aiofiles, предоставляющий удобный и простой интерфейс:

async with aiofiles.open('filename', mode='r') as f: contents = await f.read()


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Steal: кто крадёт у виртуалок процессорное время

Хочу рассказать простым языком о механике возникновения steal внутри виртуальных машин и о некоторых неочевидных артефактах, которые нам удалось выяснить при его исследовании, в которое мне пришлось погрузиться как техдиру облачной платформы Mail.ru Cloud Solutions. Привет! Платформа работает на KVM. ...

Почему бессмысленно писать прогнозы

Сейчас в различных СМИ да и на Хабре публикуется большое количество прогнозов о бурном развитии робототехники, беспилотных автомобилей и альтернативной энергетики. Люди зачастую настроены излишне оптимистично, и ожидают какого-то рывка. Я предлагаю посмотреть, что прогнозировали на Хабре, и каким видели ...