Дневник разработчицы
407 subscribers
111 photos
9 videos
14 files
145 links
Откровенные истории о проектах, работе, учебе и открытиях в мире программирования. Присоединяйтесь и вдохновляйтесь вместе со мной!
Download Telegram
вариант с переменной estimator - то, что было в тетрадке к курсу (это из "лекций"). Там, где побольше комментариев - то, что я сама пыталась разобрать. Сюда бы еще можно было бы добавить ссылки на документацию и краткое описание того, что делает каждая из функций. Но нет. Спасибо за курс, спасибо за дорогу к знаниям.
К сожалению, это не разовый пример, большая часть курса такая.
Может, кто-то и скажет, что тут все очевидно, но на мой взгляд, уж лучше проще, особенно для студентов, чем такое адовое нагромождение с бесконечными скобочками и lambda-функциями. Как вы это написали без ошибок то?)
JS повеяло) #Учеба
Хочу поделиться, мало ли кому-то будет полезно.
У vs code есть возможность совместной работы над кодом https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack
Эту штуку я пробовала сама и мне понравилось (спасибо Паша).
У JB тоже есть такое https://plugins.jetbrains.com/plugin/14896-code-with-me
Но в Pycharm я пока не пробовала.
Это как в гугл-доках совместная работа с текстом и табличками, только с кодом. #Tools
Последнее время никак не могу собраться и войти в стабильный ритм. Немного поделаю того, немного сего, в итоге топчусь на месте.

Зато помогая с задачкой другу, обнаружила, что я могу ориентироваться и понимать чужой код. Круто!

Попутно все размышляю как мне решить свой вопрос с большим объемом данных в таблицах, на которых идет нагрузка.
У меня есть следующие вводные:
1. модель, имеющая большую связность,
2. частое чтение данных, добавленных за последние 10 минут (несколько десятков запросов раз в минуту),
3. частая запись данных,
4. редкое чтение данных за все время (несколько раз в месяц),
5. объем данных 2,3 млн строк в одной таблице и 3,9 млн строк в другой таблице.

Основная проблема кроется в пункте 2, потому что оно создает основную нагрузку. Хочется какое-нибудь решение, чтобы данные за последние 10 минут лежали где-то в отдельном месте, откуда и считывались для скриптов из пункта 2. При этом получается, что они должны туда постоянно приходить и уходить. Но я не могу использовать не PostgreSQL, так как мне требуется полнотекстовый поиск и функцию similarity для триграмм.
Есть еще вариант с партиционированием. И даже есть инструменты для этого:
https://django-postgres-extra.readthedocs.io/en/master/index.html
https://architect.readthedocs.io/features/partition/postgresql.html
Надо заняться и разобраться с этим. Лунная призма дай мне силу!

Может, кто из подписчиков что-то интересное подскажет?

И да, приятно удивлена интересу к моему скромному дневничку.

PS.
- "это не нагрузка для бд" - нагрузка, в основном, как я поняла, проблема в оперативной памяти. Данные довольно объемные. Выводы основаны на практическом использовании и сравнении работы бд при разных ресурсах (оперативная память, процессор) и при разных объемах соответствующих таблиц.
- "есть ли индексы" - да, индексы есть, для поиска использую индекс GIN (https://docs.djangoproject.com/en/3.1/ref/contrib/postgres/indexes/#ginindex)
- Не ищу критики, ищу совета на счет варианта решения задачи. Критику на счет бд уже получала, ничего интересного не было.
В результате хочу снизить ресурсы для бд по оперативке, так как слишком дорого за нее выходит платить. #Django
~x

Очень редкий зверь - значок тильды в python. Не так просто найти о нем информацию.
Еще иногда встречается использование & и |, когда я впервые увидела их использование, меня это поставило в тупик: а что это и как это понимать.
Самый лучший список всех-всех вариантов разных операторов я нашла тут https://pythonworld.ru/osnovy/peregruzka-operatorov.html

Если стандартные операторы довольно часто используются и легко найти как их "перегружать", то вот с битовым операциями сложнее. И как гуглить такое непонятно. Поэтому сохраняю в закладки).

В некоторых библиотеках перегружают такие операторы для удобства работы.
Например, в Pandas для объединения условий внутри выражения используется как раз операторы & и |:

df.loc[(df.cnt < 1000) & (df.workingday == 0), 'hum']


В исходниках можно найти как они реализованы:


# -------------------------------------------------------------
# Logical Methods

def _logical_method(self, other, op):
return NotImplemented

@unpack_zerodim_and_defer("__and__")
def __and__(self, other):
return self._logical_method(other, operator.and_)

@unpack_zerodim_and_defer("__rand__")
def __rand__(self, other):
return self._logical_method(other, roperator.rand_)

@unpack_zerodim_and_defer("__or__")
def __or__(self, other):
return self._logical_method(other, operator.or_)

@unpack_zerodim_and_defer("__ror__")
def __ror__(self, other):
return self._logical_method(other, roperator.ror_)

Глубже не осилила.

Просто решила поделиться. #Python
Хочется написать про поиск работы.

Я иногда посматриваю вакансии и прохожу тестовые. Нет, не так, я ткнулась в пару вакансий и сделала их тестовые.
Первое тестовое было - 4 задачки на базовый синтаксис и алгоритмы. По функционалу я сделала полностью, но вот забыла про магию множеств python - функцию set.intersection() https://pythonz.net/references/named/sets.intersection/. Теперь буду пользоваться.

После меня позвали на интервью с 10 техническими вопросами. Воспроизведу то, что помню:
1. Какие СУБД знаете. Чем SQLite отличается от остальных.
2. Join и его виды, чем отличаются.
3. Сложность алгоритмов, бинарный поиск, его сложность.
4. Индексы в бд, что такое, какая сложность получения экзмепляра по индексу.
5. POST и GET запросы, в чем отличие и применение.
6. Зачем нужен GIT и его команды.
7. Базовые команды линукса. Как можно посмотреть файл, с какими редакторами работала. (не ответила, не помню).
8. Миграции джанги, зачем нужны, как создавать, как применять, какие команды соответствуют.
9. Students.objects.filter(age__gte=18).exclude(sex="F").values_list('name', flat=True) - попросили объяснить что тут происходит.

Десятый не помню) В целом я на все ответила, кроме линукса, потому что не применяю ничего, кроме cd и ls, ну, и установки пакетов, выполнения команд.

Вторая вакансия - наоброт, сначала вопросики, потом тестовое. Вопросики были на софт-скиллы.

https://meta-test-mandrianova.herokuapp.com/ - вот, что собрала для демо в итоге на тестовое. Надо было сделать загрузку данных по докторам через стороннее api и страничку доктора на vue. Чтобы сделать демку пришлось подставлять костыли, так как не хотелось ради тестового задания подключать aws s3 для загрузки media. Я еще бы с этим просидела денек.
Впервые что-то собирала на vue, впервые, кстати, выкачивала и сохраняла файлы по урлу. Мне кажется, что то, как я в итоге сделала сохранение файла в джанге - ну такое.
Решила не писать тесты, не обкладывать логами, не залипать на неделю над задачкой. В общем, сделала минимум, если честно.


Хочу еще поделиться менеджерским хаком проверки неизвестного работодателя:
- Ищем юр. лицо потенциального работодателя (на сайте, в гугле, еще может помочь сервис https://www.nic.ru/whois/)
- Идем смотреть по юр.лицу сюда https://www.list-org.com/ или на подобные ресурсы. Там видим доходы-расходы за прошлый год, фактическую инфу о компании, какие есть судебные тяжбы у работадетеля.
- Еще можно проверить соцсети, поискать нет ли знакомых, кто там работает и спросить у них как и что.


Жду ответа)

PS. Не поняла почему все так прутся от Vue (не распробовала, видимо). Надо будет еще Ангуляр потыкать палочкой. #Работа
Дотянулись ручки до Ангуляра, пока чисто ради интереса прохожу туториал. Столько всего замечательного!

<li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)" >
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>

Магия тегов!

id: number;
name: string;
}

Типизация!

ng generate service hero

Удобное создание компонентов и вообще все для людей.
А это я только начала...

Королева в восхищении!

Не претендую на умные мысли и споры на тему выбора технологий, просто захотелось поделиться, мне понравилось.) #JS
Пришел ко мне мой друг Никита и принес вот такое задание от своего знакомого:


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

И чтобы можно было получить доступ по индексу в этом дереве


И вроде слова все знакомые, но с ходу я даже не поняла, а что вообще требуется.
Мы начали обсуждать и Никита поделился своим вариантом решения, в котором он по сути реализовал дерево с помощью вложенных списков (на базе класса, конечно).
Тут уже у меня возник вопрос, а при чем тут ООП, кроме того, что структура задается с помощью класса. Где тут инкапсуляция, наследование, полиморфизм.

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



class Node:

def __init__(self, data=None):
self.nodes: List[Node] = []
self.data = data

def add(self, data):
self.nodes.append(Node(data))

def _create_empty_elements(self, key):
for n in range(len(self.nodes), key + 1):
self.nodes.append(Node())

def __setitem__(self, key, value):
if key > -1 and len(self.nodes) < key + 1:
self._create_empty_elements(key)
self.nodes[key].data = value

def __getitem__(self, item):
if item > -1 and len(self.nodes) < item + 1:
self._create_empty_elements(item)
return self.nodes[item]


Вроде задачка простая, все слова знакомые, но лично я раньше не прописывала методы getitem и setitem, поэтому решение пришло не сразу.

А закончили мы еще интересным обсуждением эффекта:


tree[0][0][2] = 'data'
tree[0][0][2].data # вернет 'data'

Так как экземпляры внутри списка того же класса, то обращения вида tree[0][0][2] двигаются по ступенькам, очень похоже на рекурсию, только это не вызов самого себя, а просто проход по разным экземплярам одного класса, где используются одни и те же методы для получения следующего. Как глубока кроличья нора!)
Интересная структура и интересная задачка, да. #Python
Про собеседования.

Говорят, что на собеседования надо ходить с мыслью, что не только компания подбирает сотрудника, но и сотрудник компанию.
Я очень не люблю собеседования, крайне. Если уж я решилась пойти, то значит я для себя уже решила, что компания мне ок. Мне обычно нечего спрашивать на собеседованиях, мне интереснее то, что спрашивают у меня, как люди реагируют на мои ответы. Если будущий руководитель задает странные вопросы, разговаривает пренебрежительно, спрашивает про стрессоустойчивость (разные люди испытывают стресс от разных вещей, но чаще это значит, что сам руководитель признает, что у них состояние филиала ада), меня это напрягает.

Вопрос денег. В нашей сфере разные компании могут себе позволить разный уровень зарплат. И при выполнении одной и той же по сути работы в одной компании специалист одного и того же уровня будет получать x, а в другой 2x. Можно получать много в финансовом секторе, на госах, в больших корпорациях, а можно меньше в стартапах или, например, идти за сколько угодно лишь бы в Яндекс. Это не значит, что в Яндексе мало платят, но у них своя религия, где ты либо с ними, либо нет. Я что хочу сказать, на самом деле, как мне кажется (и на основе небольших исследований на коллегах), для многих деньги не главный фактор выбора работы и не то, что их держит. Но это безусловно важно.
Так вот, когда меня спрашивают - сколько? У меня всегда встречный вопрос - сколько вы готовы платить мне? А дальше уже я могу согласиться, либо мы можем обсуждать. В случае, если я скажу сумму, которая кажется работодателю слишком высокой, происходит странная реакция. Часто они не торгуются, а просто сливаются. "Вас таких толпа за забором", "Зажралась", "Не, чет ссыкотно, слишком дорогой специалист" - почему нельзя просто поговорить открыто? Зачем все эти манипуляции еще на этапе начального договора?
Когда я влияла на зп людей, я всегда пыталась открыто говорить могу и готова ли я дать/повысить им зп или нет. Но большинство руководителей предпочитают скользить по этим вопросам, чтобы переиграть и сэкономить. Вопрос, а какой в этом профит? Просто у сотрудника останется осадок, он начнет смотреть налево не из-за денег, а из-за того, что будет чувствовать себя обманутым.

Про странные и "правильные" вопросы. Как человек решает проблемы, какие проблемы были на его пути и что он делал, какой у него был релевантный опыт, что интересно/неинтересно человеку - это, я считаю правильными вопросами. Очень не люблю всякие абстрактные задачки, которые направлены на то, чтобы выявить о том, как человек мыслит. Например, вот вас попросили сделать это и это, как будете действовать. Хз, может у меня фантазия не очень, но то как я рассуждаю на собеседовании и то, как я реально буду делать - абсолютно разные пути. Я в реальности прежде чем что-то делать 100 раз подумаю и посмотрю на проблему с разных сторон, чтобы понять с чего начать. В фантазиях же ответом на вопрос, как правило, ожидается конкретный алгоритм, который составил для себя тот, кто спрашивает. И вот, давай поиграем в игру, угадайте, что задумал ваш собеседник.
Помню, было смешно, когда я дала определение одному понятию, а человек по ту сторону стола сказал, что это неправильно и сказал тоже самое, но другими словами. Ну ок, вам виднее, ведь правильность ответа в данном случае вещь субъективная.
Вопросы про знания. Человек знающий не равно человек применяющий, умеющий применять. Но со знанием всегда лучше, чем совсем без него.
Ну и на последок. Всякие психологические вопросы на выявление характера. На самом деле, и без них невербально чаще всего каждый участник считывает было ли ему комфортно общаться, чаще выбирают тех, с кем было приятно. Но бывает, что и нет. Я один раз согласилась пойти туда, где гендир мне прямым текстом сказал "вы мне не очень нравитесь, но я готов попробовать", в итоге мы с ним неплохо сработались, хотя процесс "притирки" был довольно долгим. И да, это с их стороны меня месяц уговаривали все же пойти к ним. Казалось бы, обе стороны на собеседовании не были в восторге друг от друга, но в итоге нас удалось продуктивно работать вместе. #Работа
🔥1
Так, а вообще из конкретных методик, мне очень понравилась STAR https://hr-portal.ru/story/metodika-star-dlya-prohozhdeniya-strukturirovannyh-sobesedovaniy
https://www.youtube.com/watch?v=kR6WrMLWaPA&ab_channel=EPAdvisory

Готовилась в свое время по ней к менеджерским интервью. А сейчас понимаю, что я ее уже на автомате применяла на вопросах по своему опыту джуна-программиста)

Всем удачи и лучших работодателей! #Работа, #Tools
Вышла на работу.
Первый день. Дали мне доступы, скачиваю проекты, смотрю на них у меня начинается адская паника - как вообще это разворачивать, с чего начать. Версия python у меня стоит другая, докер для локального разворачивания не предусмотрен, с дампами баз я почти ничего не делала, с ssh толком не работала.
Короче, целый день я провозилась с тем, чтобы хоть как-то поднять проект, при этом дамп пришлось оставить на следующий день.
День второй, дали первую задачу, удалось пообщаться на счет архитектуры. Долго возилась с бд, зато научилась складывать дамп в контейнер и запускать разворот базы локально. Пора писать баш-скрипты для этого.
Сделала свою маленькую первую задаченьку, отправила реквест. Божечки-кошечки. Хотела работы в команде - нате, получите, распишитесь. На 10 строк кода 100500 комментариев - тут не так, это не этак. >_< не поговнокодишь, ага!
Ладно, я не унываю, ведь комментировали даже то, что я тупо взяла из уже существующего кода. Так что нет предела совершенству!)
Завтра будет лучше.


Новым коллегам, привет!) #Работа
Познакомилась с интересной библиотекой для работы с excel. Хочу поделиться.
https://formulas.readthedocs.io/en/stable/
Итак, у меня был здоровый excel с формулами, ссылающимися на разные листы, а листов было довольно много. Внутри куча справочников, зависимостей и тд и тп. Переносить такую логику на бекенд придется месяц, разбирая по ниточке все нюансы.
Почему бы не оставить всю логику в excel и просто заполнять нужные данные? Потому что для получения результата нужно исполнение всех этих формул = открыть excel, чтобы он посчитал.
Что делает магическая библиотека formulas? Она берет excel, парсит из него все формулы и данные, переводит это на python и пересчитывает все, что нужно. Можно даже данные в исходном excel не менять.
Как пользоваться?

input_fileds = {"'[файл]НАЗВАНИЕ ЛИСТА(uppercase)'!A1": "значение"} # А1 - номер ячейки как в excel. Это словарь, можно указать в нем список всех нужных значений для расчета.
solution = xl_model.calculate(inputs=input_fileds) # в результате получаем граф со всеми-всеми заполненными ячейками из excel
result = solution.get_node("'[файл]НАЗВАНИЕ ЛИСТА(uppercase)'!B1") # Для получения конкретного поля из solution
result[0].value[0, 0] # пример как можно вытащить само значение для выбранного поля

Подробности и разные варианты использования смотрите в документации.
Обращаю внимание, что библиотека использует numpy, поэтому ее также придется подключать к проекту. В файле не должно быть битых ссылок, перед использованием проверьте, что все ок.

Пробовала в аргумент outputs для calculate() передать массив значений, которые я хочу получить в результате, но что-то пошло не так и я получила все равно все подряд. Также пыталась вытащить график зависимостей из файла, но тоже безуспешно. #Python, #Tools, #Работа
👍1
Продолжаю возиться с Ангуляром, теперь уже на проекте.

Бекенд (модельки, админку, апишки) собрала за 1 день. Потом приступила к фронту. Сначала я долго ковырялась с конфигами, но таки разобралась в итоге, чтобы разделить конфиг сборки для прода и обычный. Все это делается в angular.json. По сути я добавила только в projects->project->architect-> configurations -> production следующее:

"index": {
"input": "src/index.html",
"output": "../index.html"
},

Ну, и кроме этого в build -> options заменила outputPath на привычный "build/static" вместо dist.
Все это нужно было, чтобы подружить Ангуляр и Джангу. Я так уже делала для реакта. Получается, что когда я делаю билд для прода, у меня автоматом подставляются верные пути к статике (за это как раз отвечает deployUrl) и index.html не складывается в ту же папку статики, которую парсит джанга, а генерит рядышком, куда я прописала путь для шаблона Джанге. Шикарно!
Ну, и в переменные среды для dev версии прописала локальные хост и порт, где крутится джанга, а вот в прод оно уже будет собираться с относительными путями (вроде как абсолютные лучше, но у меня пока нет необходимости). Это нужно для подключения к web-сервисам.
Заманалась искать все эти нюансы, потому что в документации все неочевидно было для меня. И более того, я долго тупила как же вообще загуглить, чтобы найти нужную информацию.


Потом я еще долго воевала как подключить шрифты. Тоже было весело.

И наконец, сама разработка. С одной стороны структура проекта вполне себе понятная, особенно после прохождения туториала. Работать довольно приятно. Надо только еще разобраться как пользоваться material ui, а то как-то верстальщик из меня не очень.
Я тащусь от того, что ангуляр сам генерит необходимую структуру компонентов, сам тянет нужные зависимости, очень удобно.

Но! Как же непривычно со строгой типизацией type-script. Иногда горит, потому что не понимаю, что ему не нравится. А ему на все структуру подайте. ВСЕ ДОЛЖНО БЫТЬ ЧЕТЕНЬКО! Это вам не js и не python. 12 интерфейсов для отражения структуры всех-всех типов объектов. Что? Ты хочешь передать объект и обращаться к его ключам? Будь добра зафиксируй, что у тебя ключи - это строки:

[index: string]: any;
}

Не уверена, что это правильный путь, но я не придумала как иначе сделать свой цикл:
  getFilters(filters: Filter): string {
let result = '';
for (const filter of Object.keys(filters)) {
const value = filters[filter];
result += `&${filter}=${value}`;
}
return result;
}

А иначе - не, type-script топал ножкой и не хотел заводить мне мой цикл( Вот такие дела.
Но мне понравилось!) #JS, #Работа
Закончилась короткая, но дивная неделька!

Познакомилась с новым:

- декоратор lru_cache.

https://pythonz.net/references/named/functools.lru_cache/
Эта штука кэширует результат выполнения функции для одинаковых атрибутов. В моем случае при использовании библиотеки formulas парсинг excel файла занимал около 9 секунд. Закэшировав функцию с парсингом, я получила постоянный и быстрый доступ к уже готовой xl_model:
```python
@lru_cache(maxsize=2)
def get_model():
xl_model = formulas.ExcelModel().loads(EXCEL_SOURCE).finish(circular=True)
return xl_model
```

- По умолчанию в PyCharm стоит длина строки 120, а в PEP 79. Я была уверена, что PyCharm мне показывает 79, но нет. Пришлось идти в настройки и править. 79 символов - это так мало(
Есть еще такая штука https://tirinox.ru/flake8-pycharm/, но надо настраивать. Попробую как-нибудь.

- Правильный импорт файла, если он лежит в той же директории, что и скрипт:

DIR_PATH = os.path.dirname(os.path.realpath(__file__))

EXCEL = 'file.xlsx'
EXCEL_SOURCE = os.path.join(DIR_PATH, EXCEL)


Я видела, конечно, как в Django прописаны импорты, но никогда не делала сама.

- 1_000_000 == 1000000. Божечки-кошечки, это круто. Смысл в том, что число с пробелами не напишешь, а вот так норм.

- ssh и работа с ним (сейчас у опытных чуваков рука-лицо, но да, я никогда не делала этого).

Научилась выполнять команды на сервере через ssh-подключение без переключения на терминал внутри сервера.
Это типа таких вещей:
```shell
scp -i ~/.ssh/key user@host:file . # копирует файл с сервера к себе (если ключ по дефолту, то указывать его не нужно
ssh user@host 'rm file' # в кавычках команда для выполнения
```
Банально и все знают? Я раньше не работала с ssh, для меня это все было в новинку.

Спасибо коллегам за развитие. Познавательно.

И вроде столько всего делала сама, но из таких мелочей, наверное, начинает складываться мастерство. #Python, #Работа, #Tools
В - внимательность.

После прохождения код-ревью своих задач осознала, что мне очень сильно не хватает внимательности к мелочам. Часто вылезают даже не ошибки, а дублирование проверок, повторные однотипные действия, которые стоило бы замечать.
Например, 5 строчек назад стояло условие if value is None, а я внутри этого условия присваиваю value = None. Зачем? Просто потому что) И потом не вижу этого. Ну, я ж все правильно написала?!)
И таких мелочей довольно много. Сама за собой, естественно, я этого не замечала.

Интересно, как прокачать этот скилл? #Работа
Из менеджера в разработчики.

Я была неплохим менеджером - Кромеритой. Сейчас пишу код и наслаждаюсь этим. Мне нравилась моя работа, нравилось управлять проектами, командами, нравилось писать тз, заниматься бизнес-аналитикой, выстраивать процессы, я спокойно, в целом, брала на себя ответственность, что важно для менеджера. Но я все время хотела программировать. Я хотела сама писать код, сама собирать проекты, сама придумывать архитектуру. Я верила, что если я стану разработчиком, то я буду неплохим специалистом.
Мне было очень жаль, что я не начала программировать еще в школе, что не знала об этом дивном мире тогда. Мне было довольно сложно начинать все с нуля, когда я все же решилась перейти в программирование. И даже теперь, я иногда испытываю отчаяние от того, что как разработчику мне еще расти и расти, что нужно еще много времени, чтобы подняться на хороший уровень. Но я на пути и это главное. #Работа, #Истории
Итоги недели)

Я тут решаю занимательную задачу - выделение существующего функционала в отдельный сервис. Хочу поделиться впечатлениями.

Django.

Отдельный сервис, свежая джанга, но та же бд. Копирую существующие модели в новое приложение, прописываю существующие таблицы так:

class Meta:
db_table = 'old_app_model'

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

Celery и Telegram.

Я уже работала с Celery ранее на своем проекте. Использовала админку для создания нужного расписания. Смотрела ход выполнения в логах.
Сейчас я научилась выводить список задач в очереди и список выполняемых задач:

i = app.control.inspect()
active_workers_tasks: dict = i.active()
scheduled_workers_tasks = i.scheduled()

app в данном случае приложение Celery:

from celery import Celery
app = Celery('name')

Это все я выведу на страничку, чтобы пользователь мог видеть, что происходит. Эдакий кастомный мониторинг. На самом деле для Celery есть Flower https://docs.celeryproject.org/en/stable/userguide/monitoring.html#flower-real-time-celery-web-monitor, но он избыточен в нашем случае.
А по результатам выполнения задачек настроила уведомления в Telegram. Делаю это на базе Celery Signals https://docs.celeryproject.org/en/stable/userguide/signals.html

@task_success.connect
def task_success_notify(signal, sender, result, **kwargs):
tag = make_tag('success')
notify_data = make_notify_task_params(sender.request)
notify_data["Результат"] = result
text = tag + make_text_from_dict(notify_data)
send_message(text)

С названиями функций у меня пока не очень( Сама чувствую, что идиотское название, но ничего пока лучше не пришло. Буду еще причесывать.
Из странного. Почему-то когда попыталась перенести отлавливание сигналов из стандартного файла tasks.py, сохранив все зависимости и тп, сигналы перестали срабатывать. Подозреваю, что для Celery важно прописывать пути, где лежат задачи и сигналы, при этом tasks.py в приложении вроде как работает по умолчанию. Но не копала пока точно эту тему, оставила в tasks.py.

Docker! Куда ж без него.

В docker-compose для того, чтобы локально поднять новый сервис, но подключиться к бд и Redis другого сервиса пришлось прокинуть network от исходного сервиса (venv_my-network):

  networks:
venv_my-network:
driver: bridge
external: true

И прописать в исходном проекте в конфиге алиасы для бд и Redis:
      networks:
my-network:
aliases:
- redis

Есть еще вариант прокидывать connect с помощью команды:

docker network connect --alias db venv_my-network container_id


Задача очень интересная. Надеюсь, что в результате все получится классно и удобно. Пока это только наброски. #Django, #Docker, #Работа
Индексы, бл**Ь! Говорили мне все, говорили... Я им - у меня вон gin-индекс! У меня все хорошо с ними, вот только память чет уходит и вообще боль.

Ну что же. Я сегодня добавила индексы для дат. БД наконец-таки отпустило! Ура!

Просто. Тупо. Индексы для дат.

add_date = models.DateTimeField(auto_now_add=True, db_index=True)


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

Но это мелочи по сравнением с тем, что я наконец смогла скинуть ресурсы для бд до 2 cpu и 2 ГБ памяти. Ура, товарищи! #Работа
Сижу, тыкаю цены Яндекс Облака, выглядит вроде как несколько дешевле, чем aws. С другой стороны, я использую дешевые споты на aws за 1.2 - 1.4 цента в час или около 650 рублей в месяц за t3.medium 2 cpu и 4 памяти. Но вот бд у меня в RDS - это отдельный специальный инстанс, очередь в sqs, логи в cloud watch, не говоря про то, что крутится на lambda и использование api gateway для endpoint. Очень распределенная система, так сказать. Не хватает только подключение к S3 для хранения медиа, о чем я давно думаю, но никак не соберусь сделать.
И вот все начинают с одной машины, на которой все это поднимают. А я сразу строила чертов замок. И как-то ненормально пытаться теперь все это собрать на одну машинку. Да?)
И вроде я все это сделала не от большого ума и опыта, а просто потому что просто как-то так вышло. Один очень влиятельный господин сразу запинал меня в aws и пришлось крутиться) Как смогла, так и выкручивалась. Мы ж не ищем легких путей.
В общей сумме за февраль за aws было выплачено 83.52 доллара (около 6300 рублей). Это на самом деле как-то дофига. Но я жду, что после оптимизации базы данных стоимость упадет почти на 26 долларов до 57.6 долларов или будет около 4500 рублей в месяц.
На облаке если посчитать все, что мне нужно, наверное, в итоге выйдет примерно также.
Еще есть вариант с Digital Ocean, там тоже вроде цены не кусачие.
Но! Если aws еще подкрутить, то там тоже можно еще немного сбить цену. Плюс я уже начала любить aws (стокгольмский синдром?!). На самом деле ковыряться с инфрой - то еще удовольствие. Наверное, оставлю пока все как есть. #AWS
Нафлудила я за эти выходные) Зашлифую! Мой идеальный офис дома. #Жизнь
🔥1
Дневник можно переименовать в еженедельник)

Отчет за недельку:

Докер

Продолжаю познавать докер и перестаю его бояться. Узнала про команды:

- docker stats - выводит состояние запущенных контейнеров (использование CPU, памяти, сети и тп).
Узнала знаете как? Первый раз у меня докер сожрал 18 ГБ памяти, а второй раз проц ушел в полку. Я решила, что хватит это терпеть, пора все же посмотреть, что там происходит.

- docker-compose up container -d
Эта приставка -d делает так, чтобы докер не начал срать своими логами в терминал, когда его запускаешь. Надоело переоткрывать терминал, поэтому сходила и посмотрела как это нормально делается.

Ну и плюс узнала как задать лимит по памяти для контейнера. Но почему-то то, что работало у меня на компе, не завелось на сервере.

logging

Когда я писала логирование для своего проекта, я просто узнала как логировать, написала свою простенькую функцию для логирования (вроде писала о ней выше) и мне было норм. Все мои логи aws заботливо собирает в CloudWatch, там прекрасный интерфейс и я довольная всегда имею доступ ко всем последним событиям на своем проекте, и не только к последним. AWS все сделал за меня! Почти все, функции обкладывала логами все же сама.
А тут на работе понадобилось логи складывать в текстовые файлики и очищать их со временем чем-нибудь, чтобы не засоряли пространство. При этом еще стоило их разделять на отдельные файлики. И пришлось мне таки разобраться как вообще работает logging.
Мне посоветовали https://www.youtube.com/watch?v=qqdgynJ5ATU это видео, но это уже после того как я перерыла кучу инфы в интернете и наваяла вот это:

```python
import logging
import logging.handlers
import os

def get_logger(filename: str):
"""
Функция возвращает logger по имени и сохраняет логи в файлы с
соответствующим названием, разделяя по часам
:param filename: название для logger
:return: logger
"""
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)

logger = logging.getLogger(filename)
logger.propagate = False
if not logger.handlers:
log_path = os.path.join(LOG_DIR, f"{filename}.log")
file_handler = logging.handlers.TimedRotatingFileHandler(
log_path, when='h', interval=1, backupCount=90
)
log_formatter = logging.Formatter("[%(levelname)s] "
"%(asctime)s %(message)s")
file_handler.setFormatter(log_formatter)
logger.addHandler(file_handler)
logger.setLevel('INFO')

return logger
```

Главные открытия:
- обработчики (handlers) сделают всю грязную работу за меня. TimedRotatingFileHandler разделяет файлы по заданным промежуткам времени, параметр backupCount указывает на то, через какое количество созданных файлов их надо чистить.
- форматирование Formatter. Для него полезно знать о том, какие атрибуты вообще есть у лог-записи https://docs.python.org/3/library/logging.html#logrecord-attributes. Я там обнаружила, что есть та вещь, которую я в свое время прописывала ручками в своей функции, а именно funcName - название функции, в рамках которой залогирована запись.

Это круто. Я понимаю, что языки программирования не дураки пишут и библиотеки тоже. Дураки (незнающие) пользуются всем этим добром криво-косо и страдают. А там такое вот чудо.

О дивный новый мир. #Python, #Docker, #Работа