Pull to refresh

Comments 11

Что-то вроде того. Только куда больше простор для использования. Едва ли не для всего что может быть представлено в виде поготовка-действие-завершение

Жаль, что в статье не рассмотрено применение в юнит тестах - удобно всякую фигню мокать на ходу.

Ещё в питоне можно вызвать несколько контекстов одновременно - через вложенные with или вот так

with A() as X, B() as Y, C() as Z:

Вопрос со звёзочкой: в сколько контекстов можно зайти одновременно? :D

Достаточно времени прошло. Можно узнать ответ?)

Я чуть мозг не сломал с последним примером.
old_mask = None, потом old_mask = umask(mask), а финалка umask(old_mask). Наивно получается, что устанавливается новая маска, хотя вокруг написано про "временно".
Я знаю umask, но я не знаю как именно работает umask, ну не было у меня опыта поработать плотно.
Полез в код:
https://github.com/certbot/certbot/blob/master/certbot/certbot/compat/filesystem.py#L64

Добавь плиз для контекста, что ОНО возвращает предыдущую маску

def umask(mask: int) -> int:
    """
    Set the current numeric umask and return the previous umask. On Linux, the built-in umask
    method is used. On Windows, our Certbot-side implementation is used.
    :param int mask: The user file-creation mode mask to apply.
    :rtype: int
    :return: The previous umask value.
    """
    if POSIX_MODE:
        return os.umask(mask)

    previous_umask = _WINDOWS_UMASK.mask
    _WINDOWS_UMASK.mask = mask
    return previous_umask

Контекст менеджеры в питоне это компромисс между читабельностью и явностью (в смысле explicit is better than implicit). Используя контекст менеджер нужно постоянно держать в голове его особенности: Single Use, Reusable or Reentrant, помноженные на потокобезопасность и возможность использовать с async - пользовательский код будет выглядеть абсолютно одинаково, а поведение существенно разным.

Например:

# Где-то в другом файле
…
with filesystem.temp_umask(mask):
    util.set_up_core_dir(...)

Как поведет себя этот код будучи вызванным одновременно в разных потоках с разными значениями mask?

Ох мне недавно понадобилось сделать что то подобное, голову сломал.

Если на примерах покажете то же создание и завершение сессии в БД, либо к стороннему API, в рамках синхронного/асинхронного подхода. Я думаю сообществу это бы понадобилось.

Обычно в документации к коннекторам это есть.

Если какое-то API требует действия после работы, но не имеет контекстного менеджера, я взял себе за правило делать его самостоятельно, благо это очень легко.

Асинхронные контекстные менеджеры тоже есть, но я с ними не работал, но в общем идея та же, только внутри можно await использовать.

__aenter__ и __aexit__, хоть то и не большое отличие, но реализация другая.

Пожалуйста, в исходники asyncpg, там как раз асинхронные контекстные менеджеры - для создания пула, получения коннекшена из пула, создания транзакции и др. Например, вот и вот

В Python множество инструментов, которые могут помочь улучшить читаемость кода, и Context manager, о котором дальше пойдет речь, один из них.


Не уверен, что контекстный менеджеры для читаемости, это больше инструмент позволяющий два завязанных по времени выполнения действий, выполнить в заданном порядке и с гарантией вызова обоих действий. Такой подход избавляет от возможных человеческих ошибок. По моему опыту почти все, кто открывают файл руками, не закрывают его правильно.

Sign up to leave a comment.