TGTGInsighttelegram intelligenceLIVE / telegram public index
← Python Заметки
Python Заметки avatar

TGINSIGHT POST

Post #161

@pythonotes

Python Заметки

Прегледи1,200Број на прегледи
Објавено9 окт.09.10.2020 г., 09:00
Содржина

Содржина на објавата

🖨Зачем подменять стандартную функцию print()? В Python3 директива print() стала функцией, то есть объектом, с которым мы можем делать что угодно. Во 2-м Python мы такого лишены. Как можно изменить стандартное поведение этой функции? Обычно подменяют объект sys.stdout, что работает и во 2-м. Но будем действовать через builtins. При этом изменим только функцию print(), а stdout останется прежним. Что нам потребуется сделать? 1. Создать функцию, которая заменит print и не сломает стандартное поведение 2. Подменить объект builtins.print import builtins _print = builtins.print builtins.print = lambda *a, **kw: _print(*a, **kw) В примере выше я заменил print но не добавил никакого функционала. Сейчас print() работает как и прежде, только через посредника. Давайте думать варианты. 🔸Изменить аргументы по умолчанию. Порой во время разработки приложения требуется именно распечатывать информацию в консоль через print(). Если это сервер, то всякий раз приходится дописывать flush=True чтобы очищался буфер вывода и мы видели в консоли текст сразу же. Давайте сделаем так чтобы этот аргумент по умолчанию был True. Тогда лямбда будет выглядеть так: lambda *a, **kw: _print(*a, **{**kw, 'flush': True}) 🔸Поиск принтов в коде. Приходилось пару раз рефакторить код сервера с очень запутанной структурой. На этапе избавления от принтов я не мог найти где распечатывается пустой список?! Ни одного принта по проекту нет а он распечатывается😢 Давайте заставим функцию print() сообщать нам где она находится. import builtins, sys _print = builtins.print def _located_print(*args, **kwargs): _print(*args, **kwargs) f = sys._getframe().f_back _print('=> File:', f.f_code.co_filename, '| line', f.f_lineno) builtins.print = _located_print Выйдет примерно так: >>> print('Hello') Hello => File: /path/to/script.py | line: 1 🔸Как-либо модифицировать все принты. Например добавлять что-то в начале, изменять цвет, заменять символьные смайлы на юникод и тд. Вот пример от меня. В Python 3.8 добавили возможность через f-string распечатывать имя переменной вместе с её значением: >>> value = 123 >>> print(f"{value=}") value=123 Аналогичный функционал я повторил через подмену функции print(). 🌎 Полный код здесь 🔸Отключить принт повсеместно! Да, бывает и такое нужно). Кроме простого отключения (код сами догадайтесь какой) можно заменять всё на одинаковое сообщение, сделав принт бесполезным. Чтобы не использовали принт в проектах! import builtins _print = builtins.print builtins.print = lambda *a, **kw: _print("Don't use prints!") Получится что-то такое >>> print('Debug message') Don't use prints! Но это больше похоже на шутку, реализовать которую помогут стартап скрипты, о которых юзер не догадывается 😝 🔸Заменить все принты на нормальное логирование. Тоже вариант, но не особо полезный. Лучше писать нормальный логгинг чем так "костылять". Ну а для тренировки можно попробовать реализовать и этот вариант. Думаю, сами справитесь) _________________________ Стоить ещё учесть пару моментов: - эту подмену следует делать в самом начале работы приложения, в скрипте с которого начинается запуск. Удобно делать через стартап скрипт. Исходники при этом менять не требуется. - функция изменится повсеместно во всех модулях на время сессии - stdout не изменён, то есть обычный логгер будет писать в консоль нормально. - Мы подменяем функцию на другую, а значит help(print) не покажет нам документацию, __name__ будет неверный и тд. Так что не забывайте использовать functools.wraps - в моих примерах кое-где не обрабатывается kwargs. Не копируйте вслепую, всегда понимайте что делаете или не делайте вовсе. Присылайте в коменты свои варианты! 😎 #tricks