День открытых дверей по курсу «Python-разработчик. Продвинутый уровень» 17.02.2020 в 20:00 | OTUS >
Проходил 17 февраля 2020 года в 20:00

День открытых дверей
Всё о курсе «Разработчик Python»

День открытых дверей онлайн

День Открытых Дверей — отличная возможность узнать подробнее о программе курса, особенностях онлайн-формата, навыках, компетенциях и перспективах, которые ждут выпускников после обучения. Также преподаватель расскажет о своём профессиональном опыте и ответит на вопросы участников. Поэтому если есть вопрос, запишитесь на онлайн-трансляцию и задайте его в прямом эфире!
Преподаватель
Станислав Ступников

Запись

О курсе

Python-разработчик. Продвинутый уровень
166 000 ₽
5 месяцев
Начало 26 августа

Для кого этот курс?

Профессиональный онлайн-курс для тех, кто уже имеет опыт программирования на Python и хочет повысить свой уровень за счет новых знаний и навыков из различных областей разработки. Если вы уверенно чувствуете себя с Python, помните C, имеете представление о сетевом взаимодействии и реляционных СУБД, умеете обращаться с Linux, Git и прочими стандартными инструментами девелопера — курс для …

Программа курса
Модуль 1
База
Модуль 2
Web-программирование
Модуль 3
ML Engineering
Модуль 4
Highload
Модуль 5
Проектная работа
База
Этот модуль посвящен рассмотрению фундаментальных основ языка на продвинутом уровне, а также применению общих практик разработки ПО в контексте «экосистемы» Python. Целью является достижение единого понятийного аппарата, формирование представления о внутреннем устройстве языка, его возможностях, ограничениях, недостатках и области применимости.
В модуле рассматриваются нюансы настройки окружения разработчика, аспекты функционального, процедурного и ООП программирования на Python, особенности устройства виртуальной машины, вопросы обеспечения качества ПО и автоматизации инфраструктурных задач.
Структура проекта, управление зависимостями, настройка окружения: обзор и лучшие практики // ДЗ
разобрать стандартный шаблон структуры Python проекта;
рассмотреть различные инструменты по управлению зависимостями;
научиться создавать удобное окружение для разработки.
27 августа, 20:00 — 21:30
Домашние задания: 1
ДЗ
Анализатор логов. Жил-был чудный веб-интерфейс, и все у него было хорошо: в него входили пользователи, что-то там кликали, переходили по ссылкам, получали результат. Но со временем некоторые его странички стали тупить и долго грузиться. Менеджеры часто жалуются, мол, «вот тут список долго грузился» или «интерфейсик тупит, поиск не работает». Но так трудно отделить те случаи, где проблемы на их стороне, а где действительно виноват веб-сервис. В логи reverse proxy перед интерфейсом (nginx) добавили время запроса (`$request_time` в `nginx`, http://nginx.org/en/docs/http/ngx_http_log_module.html#log_format). Теперь можно распарсить логи и провести первичный анализ, выявив подозрительные URL'ы.

Про логи:

* Семпл лога: `nginx-access-ui.log-20170630.gz`
* Шаблон названия логов: `nginx-access-ui.log-YYYYMMDD.gz`
* Так вышло, что логи могут быть и plain (т. е. «сырые», без сжатия) и gzip
* Лог ротируется раз в день
* Опять же так вышло, что логи интерфейса лежат в папке с логами других сервисов

Про отчет:

* count — сколько раз встречается URL, абсолютное значение
* count_perc — сколько раз встречается URL, в процентах относительно общего числа запросов
* time_sum — суммарный $request_time для данного URL'а, абсолютное значение
* time_perc — суммарный $request_time для данного URL'а, в процентах относительно общего $request_time всех запросов
* time_avg — средний $request_time для данного URL'а
* time_max — максимальный $request_time для данного URL'а
* time_med — медиана $request_time для данного URL'а


*Задание*: реализовать анализатор логов `log_analyzer.py`.

__Основная функциональность__:

1. Скрипт обрабатывает при запуске последний (со самой свежей датой в имени, не по mtime файла!) лог в `LOG_DIR`, в результате работы должен получится отчет как в `report-2017.06.30.html` (для корректной работы нужно будет найти и принести себе на диск `jquery.tablesorter.min.js`). То есть скрипт читает лог, парсит нужные поля, считает необходимую статистику по url'ам и рендерит шаблон `report.html` (в шаблоне нужно только подставить `$table_json`) в `report-YYYY.MM.DD.html`, где дата в названии соответствует дате обработанного файла логов. Ситуация, что логов на обработку нет, возможна, это не должно являться ошибкой.
2. Готовые отчеты лежат в `REPORT_DIR`. В отчет попадает `REPORT_SIZE` URL'ов с наибольшим суммарным временем обработки (`time_sum`).
3. Скрипту должно быть возможно указать считать конфиг из другого файла, передав его путь через `--config`. У пути конфига должно быть дефолтное значение. Если файл не существует или непарсится, нужно выходить с ошибкой.
4. В переменной `config` находится конфиг по умолчанию. В конфиге, считанном из файла, могут быть переопределены переменные дефолтного конфига (некоторые, все или никакие, т. е. файл может быть пустой), и они имеют более высокий приоритет по сравнению с дефолтным конфигом. Таким образом, результирующий конфиг получается слиянием конфига из файла и дефолтного, с приоритетом конфига из файла. Ситуацию, когда конфига на диске не оказалось, нужно исключить.
5. Использовать конфиг как глобальную переменную запрещено, т. е. обращаться в своем функционале к нему так, как будто он глобальный, нельзя. Нужно передавать как аргумент.
6. Использовать сторонние библиотеки для реализации основного функционала запрещено, за исключением `structlog`.
7. (задание со «звездочкой») Если скрипт удачно обработал, то работу не переделывает при повторном запуске.

__Мониторинг__:

1. Скрипт должен писать структурированные логи в JSON через [structlog](https://www.structlog.org/en/stable/why.html) (плюс рекомендуется познакомиться с утилитой [jq](https://jqlang.github.io/jq/)). Допускается только использование уровней `debug`, `info`, `error`. Путь до лог-файла указывается в конфиге, если не указан, лог должен писаться в stdout.
2. Все возможные «неожиданные» ошибки должны попадать в лог вместе с трейсбеком. Имеются в виду ошибки, непредусмотренные логикой работы, приводящие к остановке обработки и выходу: баги, нажатие Ctrl+C, кончилось место на диске и т. п.
3. (задание со «звездочкой») Должно быть предусмотрено оповещение о том, что большую часть анализируемого лога не удалось распарсить (например, потому что сменился формат логирования). Для этого нужно задаться относительным (в долях/процентах) порогом ошибок парсинга и при его превышании писать в лог, затем выходить.

__Тестирование__:

На скрипт должны быть написаны тесты с использованием библиотеки `pytest`. Тестируемые кейсы и структура тестов определяется самостоятельно (без фанатизма, достаточно каких-нибудь разумных тестов, занятия про тестирование ждут нас впереди).

__Оформление__:

1. Задать проекту типовую структуру (можно ориентироваться https://realpython.com/python-application-layouts/ или свои любимые крупные проекты на github).
2. Настроить pre-commit хуки, как минимум линтер, black, isort, mypy и poetry.
3. Настроить CI со стандартными проверками: линтер, black, isort, mypy — и запуском тестов.
4. Написать README.md с его кратким описанием и примерами запуска.
5. Настройку и управление зависимостями провести через poetry и pyproject.toml (ну и, возможно, setup.cfg).
6. Подготовить Makefile для удобного запуска линтовки, тестов (и тестового покрытия) и самого приложения.
7. (задание со «звездочкой») Подготовить Dockerfile, собранный образ должен уметь по подключенным через volume входным данным (директория с логами, конфиг) выдавать в этот же или другой volume отчет.


*Цель задания*: получить (прокачать) навык создания полноценного проекта. То есть проекта, наполненнго адекватным кодом, который удобно расширять и поддерживать, протестированного, пригодного для мониторинга, имеющего стандартную структуру, минимальное описание и настроенный CI. Совпадение всех чисел с приведенным примером отчета целью не является (лишь бы похожи были =)



__Распространенные проблемы__:

* Не стоит делать свои кастомные классы ошибок, это иногда (!) имеет смысл для библиотек, но не для задач подобного рода.
* Ограничьтесь уровнями логирования DEBUG, INFO и ERROR: https://dave.cheney.net/2015/11/05/lets-talk-about-logging
* Не выходите через sys.exit не из main. Это затрудняет тестирование и переиспользование кода.
* Чтобы отрендерить шаблон, не надо итерироваться по всем его строкам и искать место замены, можно воспользоваться, например, https://docs.python.org/3/library/string.html#string.Template.safe_substitute.
* Функцию, которая будет парсить лог, желательно сделать генератором и передать в качестве аргумента функции создателю отчета.
* Не забывайте про кодировки, когда читаете лог и пишете отчет.
* Из функции, которая будет искать последний лог, удобно возвращать namedtuple/dataclass с указанием пути до него, распаршенной через datetime даты из имени файла и расширением, например.
* Распаршенная дата из имени лог-файла пригодится, чтобы составить путь до отчета, это можно сделать «за один присест», не нужно проходится по всем файлам и что-то искать.
* Протестируйте функцию поиска лога, она не должна возвращать .bz2 файлы и т. п. Этого можно добиться правильной регуляркой.
* Найти самый свежий лог можно за один проход по файлам, без использования glob, сортировки и т. п.
* Нужный открыватель лога (open/gzip.open) перед парсингом можно выбрать через тернарный оператор.
* Проверка на превышение процента ошибок при парсинге выполняется один раз, в конце чтения файла, а не на каждую строчку/ошибку.
* Коммитить толстые бинари (например nginx-access-ui.log-20170630.gz) в git не стоит, он для исходного кода, в основном.

__Полезные ссылки__:

* https://docs.python.org/3/library/statistics.html
* https://jesseduffield.com/Beginners-Guide-To-Abstraction/
* https://melevir.medium.com/короче-говоря-принцип-единой-ответсвенности-92840ac55baa
* https://melevir.medium.com/python-стиль-кода-1af07092836e
* https://melevir.medium.com/дизайн-функций-a63bc9588e11
* https://www.youtube.com/watch?v=o9pEzgHorH0 Stop Writing Classes
* https://leontrolski.github.io/mostly-pointless.html
* https://blog.guilatrova.dev/handling-exceptions-in-python-like-a-pro/
* https://mitelman.engineering/blog/python-best-practice/automating-python-best-practices-for-a-new-project/
* https://medium.com/@vanflymen/blazing-fast-ci-with-github-actions-poetry-black-and-pytest-9e74299dd4a5

## Deadline
Задание желательно сдать в течение недели. Код, отправленный на ревью в это время, рассматривается в первом приоритете. Нарушение делайна не карается. Пытаться сдать ДЗ можно до конца курса. Код, отправленный с опозданием, когда по плану предполагается работа над более актуальным ДЗ, будет рассматриваться в более низком приоритете без гарантий по высокой скорости проверки.

## Обратная связь
Cтудент коммитит все необходимое в свой github/gitlab репозитарий. Далее необходимо зайти в ЛК, найти занятие, ДЗ по которому выполнялось, нажать “Чат с преподавателем” и отправить ссылку. После этого ревью и общение на тему ДЗ будет происходить в рамках этого чата.


### Материалы для выполнения ДЗ:

[https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/4ba19c1e0b2be7609f098c2c3461de30878a5aab/homework_01_log_analyzer](https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/4ba19c1e0b2be7609f098c2c3461de30878a5aab/homework_01_log_analyzer)
Дистрибуция кода и развертывание: путь от лэптопа до кластера
рассмотреть различные способы сборки Python-проектов;
обсудить способы и каналы дистрибуции проектов;
изучить лучшие практики по контейнеризации Python-приложений;
рассмотреть Kubernetes в качестве основной среды для запуска контейнеров.
3 сентября, 20:00 — 21:30
Аннотации типов: уровень nightmare! // ДЗ
познакомиться с теорией типов и изучить особенности ее применения к Python;
рассмотреть возможности аннотации типов, разобрать кейсы;
изучить существующие варианты и инструменты для проверки аннотаций.
8 сентября, 20:00 — 21:30
Домашние задания: 1
ДЗ
Тренажер по аннотации типов. *Задание*: пройти максимальное количество упражнений на аннотацию типов в тренажере https://python-type-challenges.zeabur.app.

*Цель задания*: набить руку на стандартных (и не очень) кейсах по типизации, попробовать на практике различные возможности языка по аннотации.

__Оформление__:
Так как на сайте тренажера нет никакого ЛК, то предлагается решенные задания сохранить в свой репозиторий (по модулю на каждое задание), настроить CI, который будет проверять аннотации с помощью mypy или pyright, а также обеспечить условия, при которых в локальном репозитории по команде `make typing` в контейнере запускалась бы аналогичная проверка типов.

## Deadline
Задание желательно сдать в течение недели. Код, отправленный на ревью в это время, рассматривается в первом приоритете. Нарушение делайна не карается. Пытаться сдать ДЗ можно до конца курса. Код, отправленный с опозданием, когда по плану предполагается работа над более актуальным ДЗ, будет рассматриваться в более низком приоритете без гарантий по высокой скорости проверки.

## Обратная связь
Cтудент коммитит все необходимое в свой github/gitlab-репозиторий. Далее необходимо зайти в ЛК, найти занятие, ДЗ по которому выполнялось, нажать «Чат с преподавателем» и отправить ссылку. После этого ревью и общение на тему ДЗ будет происходить в рамках этого чата.
Внутренности: байткод, его исполнение и виртуальная машина
разобраться с устройством виртуальной машины;
рассмотреть процесс исполнения кода;
рассмотреть фундаментальные абстракции, которыми оперирует виртуальная машина.
10 сентября, 20:00 — 21:30
Внутренности: устройство основных типов, управление памятью и GIL
разобраться с работой основных типов данных и следствиями такой реализации;
рассмотреть процесс управления памятью в Python;
объяснить, как GIL влияет на производительность Python-программ.
15 сентября, 20:00 — 21:30
ООП: Объектная модель и особенности ООП в Python // ДЗ
изучить устройство объектной модели Python;
разобраться с разделением на новые и классические классы;
объяснить тонкости множественного наследования;
разобраться с нюансами реализации ООП в Python.
17 сентября, 20:00 — 21:30
Домашние задания: 1
ДЗ
API скоринга. *Задание*: реализовать декларативный язык описания и систему валидации запросов к HTTP API сервиса скоринга. Шаблон уже есть в api.py, тесты в test.py, функционал подсчета скора в scoring.py. API необычно тем, что пользователи дергают методы POST запросами. Чтобы получить результат, пользователь отправляет в POST запросе валидный JSON определенного формата на локейшн /method.

*Disclaimer*: данное API ни в коей мере не являет собой best practice реализации подобных вещей и намеренно сделано «странно» в некоторых местах.

*Цель задания*: применить знания по ООП на практике, получить навык разработки нетривиальных объектно-ориентированных программ. Это даст возможность быстрее и лучше понимать сторонний код (библиотеки или сервисы часто бывают написаны с примененем ООП парадигмы или ее элементов), а также допускать меньше ошибок при проектировании сложных систем.

### Структура запроса

```json
{
"account": "<имя компании партнера>",
"login": "<имя пользователя>",
"method": "<имя метода>",
"token": "<аутентификационный токен>",
"arguments": {<словарь с аргументами вызываемого метода>}
}
```

* account — строка, опционально, может быть пустым
* login — строка, обязательно, может быть пустым
* method — строка, обязательно, может быть пустым
* token — строка, обязательно, может быть пустым
* arguments — словарь (объект в терминах json), обязательно, может быть пустым

### Валидация

Запрос валиден, если валидны все поля по отдельности

#### Структура ответа

OK:

```json
{"code": <числовой код>, "response": {<ответ вызываемого метода>}}
```

Ошибка:

```json
{"code": <числовой код>, "error": {<сообщение об ошибке>}}
```

### Аутентификация:

Смотри `check_auth` в шаблоне. В случае если не пройдена, нужно возвращать

```json
{"code": 403, "error": "Forbidden"}
```

## Методы

### online_score

__Аргументы__:

* phone — строка или число, длиной 11, начинается с 7, опционально, может быть пустым
* email — строка, в которой есть @, опционально, может быть пустым
* first_name — строка, опционально, может быть пустым
* last_name — строка, опционально, может быть пустым
* birthday — дата в формате DD.MM.YYYY, с которой прошло не больше 70 лет, опционально, может быть пустым
* gender — число 0, 1 или 2, опционально, может быть пустым

__Валидация аргументов__

Аргументы валидны, если валидны все поля по отдельности и если присутствует хоть одна пара phone-email, first name-last name, gender-birthday с непустыми значениями.

__Контекст__

В словарь контекста должна прописываться запись "has" — список полей, которые были не пустые для данного запроса

__Ответ__

В ответ выдается число, полученное вызовом функции `get_score` (см. scoring.py). Но если пользователь админ (см. `check_auth`), то нужно всегда отдавать 42

```json
{
"score": <число>
}
```

Или если запрос пришел от валидного пользователя admin

```json
{
"score": 42
}
```

Или если произошла ошибка валидации

```json
{
"code": 422,
"error": "<сообщение о том, какое поле(я) невалидно(ы) и как именно>"
}
```

__Пример запроса__:

```sh
curl -X POST -H "Content-Type: application/json" -d '{"account": "horns&hoofs", "login": "h&f", "method": "online_score", "token": "55cc9ce545bcd144300fe9efc28e65d415b923ebb6be1e19d2750a2c03e80dd209a27954dca045e5bb12418e7d89b6d718a9e35af34e14e1d5bcd5a08f21fc95", "arguments": {"phone": "79175002040", "email": "stupnikov@otus.ru", "first_name": "Стансилав", "last_name": "Ступников", "birthday": "01.01.1990", "gender": 1}}' http://127.0.0.1:8080/method/
```

__Пример ответа__:

```json
{
"code": 200,
"response": {
"score": 5.0
}
}
}
```

### clients_interests

__Аргументы__:

* client_ids — массив чисел, обязательно, не пустое
* date — дата в формате DD.MM.YYYY, опционально, может быть пустым

__Валидация аругементов__:

Аргументы валидны, если валидны все поля по отдельности.

__Контекст__:

В словарь контекста должна прописываться запись "nclients" — количество id'шников, переданных в запрос

В ответ выдается словарь `<id клиента>:<список интересов>`. Список генерировать вызовом функции `get_interests` (см. scoring.py).

```json
{
"client_id1": ["interest1", "interest2", ...],
"client_id2": [...],
"client_idN": [...],
}
```

Или если произошла ошибка валидации

```json
{
"code": 422,
"error": "<сообщение о том, какое поле(я) невалидно(ы) и как именно>"
}
```

__Пример запроса__:

```sh
$ curl -X POST -H "Content-Type: application/json" -d '{"account": "horns&hoofs", "login": "admin", "method": "clients_interests", "token": "d3573aff1555cd67dccf21b95fe8c4dc8732f33fd4e32461b7fe6a71d83c947688515e36774c00fb630b039fe2223c991f045f13f24091386050205c324687a0", "arguments": {"client_ids": [1,2,3,4], "date": "20.07.2017"}}' http://127.0.0.1:8080/method/
```

__Пример ответа__:

```json
{
"code": 200,
"response": {
"1": ["books", "hi-tech"],
"2": ["pets", "tv"],
"3": ["travel", "music"],
"4": ["cinema", "geek"]
}
}
```

### Логирование

1. Скрипт должен писать логи через библиотеку logging в формате `'[%(asctime)s] %(levelname)s %(message)s'` c датой в виде `'%Y.%m.%d %H:%M:%S'`. Допускается только использование уровней `info`, `error` и `exception`. Путь до лог-файла указывается в конфиге, если не указан, лог должен писаться в stdout.

## Распространенные проблемы

* Суть ДЗ в том, чтобы объявить поля один раз и не дублировать больше в init или еще где-либо. Это, например (но не обязательно именно так), можно сделать с помощью метакласса, который при создании класса все Field соберет в массив, по которому можно будет итерироваться и валидировать.

## Deadline
Задание нужно сдать через неделю. То есть ДЗ, выданное в понедельник, нужно сдать до следующего занятия в понедельник. Код, отправленный на ревью в это время, рассматривается в первом приоритете. Нарушение делайна (пока) не карается, пытаться сдать ДЗ можно до конца курсы. Но код, отправленный с опозданием, когда по плану предполагается работа над более актуальным ДЗ, будет рассматриваться в более низком приоритете без гарантий по высокой скорости проверки.

## Обратная связь
Cтудент коммитит все необходимое в свой github/gitlab репозитарий. Далее необходимо зайти в ЛК, найти занятие, ДЗ по которому выполнялось, нажать “Чат с преподавателем” и отправить ссылку. После этого ревью и общение на тему ДЗ будет происходить в рамках этого чата.


### Материалы для выполнения ДЗ:

[https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/9a7c6a1536f2ea81cdb4a6068a62f65938e43b9d/api_scoring](https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/9a7c6a1536f2ea81cdb4a6068a62f65938e43b9d/api_scoring)
ООП: Дескрипторы и метапрограммирование
объяснить дескрипторы и их протокол;
разобраться с использованием «магических методов»;
рассмотреть область применимости абстрактных базовых классов;
проанализировать особенности эксплуатации метаклассов.
22 сентября, 20:00 — 21:30
Тестирование: pytest и как писать тесты // ДЗ
обсудить необходимость тестирования и когда нужно писать тесты;
разобраться с тем, что именно тестировать и как структурировать тесты;
рассмотреть pytest в качестве основного инструмента тестирования;
разобраться с устройством пирамиды тестирования.
24 сентября, 20:00 — 21:30
Домашние задания: 1
ДЗ
Тестирование. *Задание*: протестировать HTTP API сервиса скоринга. Шаблон уже есть в test.py, само API реализовывалось в прошлой части ДЗ. Тесты, выданные ранее, можно считать функциональными и уже готовыми.
1. Необходимо разработать модульные (unit) тесты на основной функционал. Разрешается пользоваться любым тестовым фреймворком: unittest, nosetests, pytest.
2. Обязательно необходимо реализовать через декоратор функционал запуска кейса с разными тест-векторами (либо, в качестве альтернативы, сделать то же самое через фикстуры в pytest). Если берете готовый cases, то его надо допилить так, чтобы при падении теста было ясно, какой кейс упал.

```
@cases([
{"account": "horns&hoofs", "login": "h&f", "method": "online_score", "token": "", "arguments": {}},
{"account": "horns&hoofs", "login": "h&f", "method": "online_score", "token": "sdd", "arguments": {}},
{"account": "horns&hoofs", "login": "admin", "method": "online_score", "token": "", "arguments": {}},
])
def test_bad_auth(self, request):
...
```

3. Store, который был захардкожен в None, наконец обретает смысл! Нужно реализовать в store.py общение с любым клиент-серверным key-value хранилищем (Tarantool, Memcached, Redis, etc.) согласно интерфейсу, заданному в обновленном scoring.py. Обращение к хранилищу не должно падать из-за разорванного соединения (т.е. store должен пытаться переподключаться N раз, прежде чем сдаться) и запросы не должны залипать (нужно использовать timeout'ы, где возможно).
* У store есть отдельно `get` и `cache_get`. В реальной системе, аналогом которой является API из ДЗ, есть отдельный кеш и отдельный key-value storage. Методы названы по-разному, чтобы показать, что есть разница. В данном случае внутри можно реализовать это и как хождение в одно и тоже хранилище. Важно то, как это будет протестировано с учетом разных требований для разных функций. Обратите внимание, функции `get_score` не важна доступность store'а, она использует его как кэш и, следовательно, должна работать, даже если store сгорел в верхних слоях атмосферы. `get_interests` использует store как персистентное хранилище и, если со store'ом что-то случилось, может отдавать только ошибки.
4. (задание со «звездочкой») Добавить интеграционные тесты нового функционала с реальным хранилищем.
5. Структура тестов: https://realpython.com/python-testing/#writing-integration-tests

*Цель задания*: применить знания по тестированию, полученные на занятии. В результате получится прокачать навык дизайна тест-кейсов, разработки модульных и функциональных тестов, создания mock'ов.


## Deadline
Задание нужно сдать через неделю. То есть ДЗ, выданное в понедельник, нужно сдать до следующего занятия в понедельник. Код, отправленный на ревью в это время, рассматривается в первом приоритете. Нарушение делайна (пока) не карается, пытаться сдать ДЗ можно до конца курса. Но код, отправленный с опозданием, когда по плану предполагается работа над более актуальным ДЗ, будет рассматриваться в более низком приоритете без гарантий по высокой скорости проверки.

## Обратная связь
Cтудент коммитит все необходимое в свой github/gitlab репозитарий. Далее необходимо зайти в ЛК, найти занятие, ДЗ по которому выполнялось, нажать «Чат с преподавателем» и отправить ссылку. После этого ревью и общение на тему ДЗ будет происходить в рамках этого чата.

#### Материалы для выполнения ДЗ:
[https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/a67555a6bb0cbbc7a05d3b6d5f05f5c7d777446e/scoring_api_tests](https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/a67555a6bb0cbbc7a05d3b6d5f05f5c7d777446e/scoring_api_tests)
Тестирование: (анти)паттерны и инструменты
разобрать антипаттерны тестирования;
рассмотреть область применения инструментов тестирования (моков, фикстур и т.д.);
разобраться с видами автоматизации тестирования.
29 сентября, 20:00 — 21:30
Дизайн кода и архитектура: абстракции, модульность, SOLID
рассмотреть подходы к формированию абстракций;
понять, что такое модульный код;
изучить SOLID-принципы к построению приложения.
1 октября, 20:00 — 21:30
Дизайн кода и архитектура: domain driven design, чистая архитектура // ДЗ
познакомиться с принципами и терминологией DDD;
изучить Clean Architecture как подход и его применимость в Python-проектах.
6 октября, 20:00 — 21:30
Домашние задания: 1
ДЗ
Чистый склад. На занятии рассматривались части приложения по управлению товарами на некоем складе. В домашнем задании предлагается расширить реализацию, добавив новые доменные объекты, репозитории, доработать unit of work. Все это необходимо сделать соблюдая принципы и подходы чистой архитектуры. Естественно реализация должна быть протестирована.
Дизайн кода и архитектура: event driven архитектура, микросервисы
рассмотреть особенности событийной модели и разобраться с ее применимостью;
изучить микросервисный подход и паттерны микросервисной архитектуры.
8 октября, 20:00 — 21:30
Дизайн кода и архитектура: паттерны проектирования
рассмотреть паттерны проектирования;
определиться с их полезностью и применимостью в разработке на Python.
13 октября, 20:00 — 21:30
Web-программирование
Этот модуль посвящен веб-разработке, тому, какой она выглядит со стороны Python программиста и какими особенностями обладает.
Целью является рассмотрение нюансов и лучших практик по созданию и эксплуатации веб-сервисов. В модуле рассматривается Django, внутреннее устройство его ORM и других его составляющих, обсуждаются особенности построения REST API на примере FastAPI, масштабирования веб-проектов.
Сетевое взаимодействие и архитектура web-серверов // ДЗ
рассмотреть принципы сетевого взаимодействия через сокеты;
разобраться с особенностями сетевых протоколов;
рассмотреть нюансы написания программ, общающихся по сети.
15 октября, 20:00 — 21:30
Домашние задания: 1
ДЗ
HTTP сервер. Разработать веб-сервер, частично реализующий протокол HTTP. Архитектуру выбрать самостоятельно.

**Условия:**
1. Разрешается использовать библиотеки для асинхронной обработки соединений, запрещается использовать библиотеки, реализующие какую-либо часть обработки HTTP. Работа с сокетами и всем остальным выполняется самостоятельно.
2. Провести нагрузочное тестирование, проверку стабильности и корректности работы.
3. Если сервер асинхронный, обязательно использовать `epoll` ([пример](https://github.com/m13253/python-asyncore-epoll)).

**Особенности реализации:**
- Отвечать кодами: `200`, `403`, `404` на GET и HEAD запросы.
- Отвечать кодом `405` на прочие запросы.
- Возвращать файлы по произвольному пути в `DOCUMENT_ROOT`.
- `/file.html` возвращает содержимое `DOCUMENT_ROOT/file.html`.
- `DOCUMENT_ROOT` задается аргументом командной строки `-r`.
- Возвращать `index.html` как индекс директории.
- `/directory/` возвращает `DOCUMENT_ROOT/directory/index.html`.
- Заголовки успешного GET-запроса: `Date`, `Server`, `Content-Length`, `Content-Type`, `Connection`.
- Корректный `Content-Type` для расширений: `.html`, `.css`, `.js`, `.jpg`, `.jpeg`, `.png`, `.gif`, `.swf`.
- Обрабатывать пробелы и `%XX` в именах файлов.
- **Звездочка:** масштабирование на несколько worker’ов. Количество worker’ов задается аргументом `-w`.

## Что проверять
- Проходят тесты: [http-test-suite](https://github.com/s-stupnikov/http-test-suite).
- В браузере корректно отображается: `http://localhost/httptest/wikipedia_russia.html`.
- Нагрузочное тестирование:
```bash
ab -n 50000 -c 100 -r http://localhost:8080/
```
или `wrk` (по желанию).

---

## На выходе

- `httpd.py` — точка входа сервера, можно разбить на модули.
- `README.md` с описанием использованной архитектуры (asynchronous / thread pool / prefork / …) и результатами нагрузочного тестирования.

---

## Цель задания

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

---


## Deadline

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

---

## Обратная связь

Студент коммитит все необходимые файлы в свой GitHub/GitLab репозиторий.
Далее в ЛК нужно найти занятие, выбрать ДЗ, нажать «Чат с преподавателем» и отправить ссылку.
Ревью и обсуждение задания проходит в рамках этого чата.

#### Материалы для выполненияя ДЗ:
[https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/40467f122b700ee382852e272b72689be3bf6c90/http_server](https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/40467f122b700ee382852e272b72689be3bf6c90/http_server)
Создание динамических страниц: от CGI до ASGI
рассмотреть принципы функционирования динамического веба;
разобраться с WSGI и его особенностями;
поговорить о различных WSGI контейнерах.
20 октября, 20:00 — 21:30
MVC/MVT фреймворки на примере Django // ДЗ
разобраться с классической структурой веб-сервисов;
рассмотреть лучшие практики развертывания Django-проектов;
объяснить, как конфигурируются и эксплуатируются Django-проекты.
22 октября, 20:00 — 21:30
Домашние задания: 1
ДЗ
Django tutorial. Домашнее задание включает два шага:

1. Пройти официальный Django tutorial и реализовать веб-сервис для блоггинга:
- модели постов, пользователей, комментариев;
- CRUD операции через ORM и Views;
- URL маршрутизация и шаблоны;
- покрытие проекта тестами.

2. Сделать проект **production-ready**, применяя рекомендации лекции:
- 12 factor apps, разделение настроек по средам;
- логирование, static/media файлы;
- развертывание через Docker, Gunicorn/Nginx;
- использование environment variables.

---

## Структура проекта
```text
blog_project/
├── blog_app/ # models.py, views.py, urls.py, tests.py, templates/
├── blog_project/ # settings/, urls.py, wsgi.py, asgi.py
├── manage.py
├── Dockerfile
├── docker-compose.yml
└── README.md
```

## Deadline

Сдать задание нужно **в течение недели после выдачи**.
Задания, отправленные вовремя, рассматриваются в приоритете.

---

## Обратная связь

1. Коммит всех файлов в ваш GitHub/GitLab репозиторий.
2. В ЛК → занятие → ДЗ → «Чат с преподавателем» → отправить ссылку на репозиторий.
3. Ревью и обсуждение задания проходит в чате.
ORM: хорошее, плохое и злое
поговорить о лучших практиках использования моделей;
объяснить, как работает ORM и из чего он состоит;
разобраться с написанием запросов через ORM;
проанализировать запросы.
27 октября, 20:00 — 21:30
Работа с БД: транзакции, репликация, шардирование и даже NoSQL
объяснить, как навигироваться в комплексном пространстве мира распределенных систем и баз данных;
познакомиться с основными понятиями, связанными с эксплуатацией и оптимизацией хранилища данных.
29 октября, 20:00 — 21:30
API: что такое настоящий REST и как создавать RESTful приложения
объяснить, что такое REST;
разобраться с лучшими практиками реализации RESTful приложений;
обсудить подходы к документированию и лимитированию запросов к API.
10 ноября, 20:00 — 21:30
FastAPI: основы // ДЗ
запустить простое приложение;
провалидировать модель запроса и ответа с помощью Pydantic;
добавить простую аутентификацию;
собрать docker-контейнер с приложением.
12 ноября, 20:00 — 21:30
Домашние задания: 1
ДЗ
ML model serving. В этом домашнем задании необходимо реализовать JSON API-сервис для инференса модели машинного обучения.

## Цель задания

Закрепить навыки работы с:

- библиотекой FastAPI для создания JSON API,
- защитой эндпоинтов с помощью базовой аутентификации,
- выполнением инференса с использованием onnxruntime,
- передачей данных в модель и возвратом предсказаний клиенту.

## Условие

У вас есть модель машинного обучения в формате ONNX (`diabetes_model.onnx`).

Она принимает на вход признаки пациента:

- `Pregnancies` (количество беременностей),
- `Glucose` (уровень глюкозы),
- `BMI` (индекс массы тела),
- `Age` (возраст).

На выходе модель возвращает вероятность наличия диабета:

- если вероятность > 0.5 → предсказание 1 (есть диабет)
- иначе 0 (нет диабета).

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

1. Принимать входные признаки через JSON API.
2. Передавать их в модель с помощью onnxruntime.
3. Возвращать предсказание в формате JSON.

Добавьте защиту: часть эндпоинтов (например, `/predict`) должна быть доступна только авторизованным пользователям через Basic Auth.

## Минимальные требования

Реализовать эндпоинт `/predict`, принимающий JSON вида:

```json
{
"Pregnancies": 2,
"Glucose": 140,
"BMI": 35.5,
"Age": 32
}
```

И возвращающий результат:

```json
{
"prediction": 1
}
```

Встроить базовую аутентификацию (по аналогии с примером на лекции).

Реализовать корневой эндпоинт `/`, который возвращает приветственное сообщение.

## Дополнительные задачи (по желанию)

Добавить валидацию входных данных через pydantic-модели.

Сделать логирование запросов и ответов.

Поднять сервис в Docker-контейнере.



#### Материалы для выполнения ДЗ:
[https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/e54bdf11462ea1178edfd28ff1add9d30c4999de/ml_model_serving](https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/e54bdf11462ea1178edfd28ff1add9d30c4999de/ml_model_serving)
FastAPI: взаимодействие с БД и SQLAlchemy
рассмотреть варианты синхронного и асинхронного взаимодействия;
проанализировать типичное CRUD-приложение;
разобраться с особенностями подключения и использования SQLAlchemy.
17 ноября, 20:00 — 21:30
Аутентификация и авторизация // ДЗ
разобраться с терминологической базой;
рассмотреть различные схемы аутентификации;
изучить способы разграничения прав пользователя;
рассмотреть стандарты и готовые инструменты.
19 ноября, 20:00 — 21:30
Домашние задания: 1
ДЗ
Аутентификация. Необходимо добавить аутентификацию по JWT-токену и минимальную RBAC-авторизацию в сервис инференса (FastAPI) из предыдущего задания.


### Исходные условия

У вас уже есть сервис FastAPI с эндпоинтом инференса модели diabetes_model.onnx (вход: Pregnancies, Glucose, BMI, Age; выход: вероятность/класс).

Базовая структура проекта и контейнеризация настроены.

#### Аутентификация (JWT)

Регистрация пользователя: ввод логина/e-mail и пароля, хранение пароля только в виде хэша.

Логин: при валидных учётных данных выдать JWT access-token.

Токен должен включать как минимум:

- `sub` (идентификатор пользователя),
- `role` (роль пользователя),
- `exp` (время истечения),
- при необходимости `iat`/`nbf`.

Параметры безопасности задаются через переменные окружения:

- секрет,
- алгоритм,
- время жизни токена.

Доступ к защищённым эндпоинтам только с заголовком `Authorization: Bearer <token>`.

#### Авторизация (RBAC)

Ввести роли: минимум `user` и `admin`.

Правила доступа:

- Эндпоинт инференса (например, `/predict`) — доступен для `user` и `admin`.
- Админский эндпоинт (например, `/admin/metrics` или `/admin/health`) — только для `admin`.
- Реализовать проверку роли на уровне зависимостей/гейткиперов (концептуально: «пользователь должен иметь не ниже заданной роли»).

#### Поведение эндпоинтов

- `/auth/register`: создать пользователя; при конфликте — понятная ошибка.
- `/auth/login`: вернуть access-token и метаданные (например, время жизни).
- `/me`: вернуть профиль текущего пользователя по токену (id/username/role).
- `/predict`: принимать валидированный JSON с признаками; возвращать результат инференса (класс и, по возможности, вероятность/скор).
- `/admin/...`: один простой админ-эндпоинт (метрики, счётчик запросов, аптайм, версия сборки и т. п.).

#### Обработка ошибок и статусы

- Отсутствует/невалидный/просроченный токен → 401 Unauthorized.
- Роль недостаточна → 403 Forbidden.
- Сообщения должны быть информативными, но без утечки чувствительных деталей (не раскрывать внутренние структуры, секреты и т. д.).

#### Валидация и надёжность

- Валидация входных данных для инференса (тип, диапазоны, обязательность полей).
- Отдельные сообщения об ошибках валидации (400 Bad Request).
- Логирование ключевых событий: аутентификация, отказ в доступе, ошибки инференса.

#### Конфигурирование

- Все секреты/параметры безопасности — через окружение (секрет ключа, алгоритм, TTL).
- Возможность задать дефолтную роль при регистрации (например, `user`).
- (Опционально) предусмотреть «сидирование» админ-пользователя для локального запуска.

### Минимальные требования (на зачёт):

- Выпуск и верификация JWT access-токена.
- Защита эндпоинта инференса токеном.
- Встроенная RBAC с отдельным эндпоинтом, доступным только роли `admin`.
- Пароли хранятся в виде хэшей.
- Документация OpenAPI (/docs) открывается, защищённые эндпоинты помечены как требующие Bearer-токена.

### Дополнительно (по желанию, +)

- Refresh-токены и обновление access-токена.
- Чёрный список/ротация токенов (logout).
- Учёт попыток логина и «заморозка» аккаунта при брутфорсе.
- Ролевые матрицы доступа, расширяемые роли.
- Трассировка запросов и метрики (например, счётчик инференсов, среднее время ответа).
- Разграничение конфигов для prod/dev (разные секреты/TTL).
API: (g)RPC, GraphQL
рассмотреть альтернативные REST подходы создания API;
сравнить подходы между собой и определиться с границами применимости.
24 ноября, 20:00 — 21:30
Безопасность: обзор распространенных проблем, уязвимостей и лучших практик
рассмотреть виды и примеры уязвимостей, которые могут возникать в приложениях на разных этапах жизни;
разобрать способы и инструменты по выявлению и устранению уязвимостей;
изучить возможности обеспечения ИБ.
26 ноября, 20:00 — 21:30
ML Engineering
Этот модуль посвящен знакомству с фундаментальными библиотеками, применяемыми для анализа данных, а также обзору современной big data экосистемы. Python является де-факто стандартом при решении аналитических задач, поэтому данный аспект языка нельзя обойти стороной. При этом целью модуля является не погружение в математические дебри, а рассмотрение таких инструментов, как jupyter, numpy, pandas и matplotlib, и области их применения в инженерной и аналитической деятельности.
Высокопроизводительные вычисления с NumPy // ДЗ
разобраться с областью применимости numpy и его основной структурой данных — ndarray;
рассмотреть индексирование и операции над массивами;
поговорить о возможностях библиотеки.
1 декабря, 20:00 — 21:30
Домашние задания: 1
ДЗ
Анализ данных и работа с массивами NumPy. ### Материалы для выволнения домашнего задания: https://gitlab.com/otus.private/python-advanced-homeworks/-/blob/0a20dcc574f85acfecac36a3b407cc309e99c5e4/numpy/hw_numpy.ipynb

## 1. Загрузка исходных данных

В приложенном файле уже написаны функции формрирования исходных данных. Но каждый раз они получаются немного другие. Вам необходимо обеспечить повторяемость исходных данных при каждом запуске

- Загрузите исходные данные
- Внесите в код изменения, которые обеспечат повторяемость исходных данных при каждом запуске.

## 2. Потренируйтесь с базовыми операциями над массивами данных

- Найдите среднюю, медианную и стандартную температуру.
- Найдите минимальное и максимальное значение и соответствующие индексы.
- Найдите дни, когда температура была выше средней.
- Сколько дней было холоднее 18 градусов?
- Разделите данные на недели (по 7 дней) и найдите среднюю температуру каждой недели.
- Вычислите скользящее среднее (по 7 дней) и сравните со средними для каждой недели.

## 3. Освойте векторные операции над массивами

Загрузите новую порцию исходных данных.

### Задание 1: Общая выручка по каждому продукту

Условие:
Считается, что каждый день продаётся по фиксированному количеству 10 единиц каждого продукта. Найдите общую выручку за год по каждому продукту с помощью скалярного произведения.

### Задание 2: День наибольшей выручки

Условие:
Определите, в какой день года суммарная выручка по всем продуктам была максимальной. То есть:
∑ (цена[i][d] × количество[i][d]) по всем i продуктов, где количество — случайные продажи в диапазоне [5, 20].

### Задание 3: Сравнение “средневзвешенной цены”

Условие:
Вычислите средневзвешенную цену каждого продукта за год, используя веса — количество проданных единиц (рандомно от 5 до 15 штук в день).
Исследовательский анализ данных c Pandas
разобраться с областью применимости pandas и его основной структурой данных — dataframe;
рассмотреть индексирование и операции над dataframe;
поговорить о возможностях библиотеки.
3 декабря, 20:00 — 21:30
Инструменты работы с данными: IPython, matplotlib, seaborn
разобраться с видовым многообразием библиотек визуализации данных в Python;
рассмотреть основные возможности matplotlib и два его интерфейса;
рассмотреть основные возможности seaborn и понять его преимущества над matplotlib;
познакомиться с основными возможностями IPython.
8 декабря, 20:00 — 21:30
Оркестрация задач: jenkins, luigi, airflow
обсудить необходимость оркестрации задач и связанные с этим сложности;
рассмотреть основные инструменты, используемые для запуска задач по расписанию.
10 декабря, 20:00 — 21:30
Нейронки: PyTorch, TensorFlow, HuggingFace и LLM // ДЗ
разобраться с тем, что из себя представляют нейронные сети;
рассмотреть основные типы сетей;
обозреть самые популярные библиотеки;
обсудить возможности применения больших лингвистических моделей.
15 декабря, 20:00 — 21:30
Домашние задания: 1
ДЗ
OTUS-GPT. В данном домашнем задании предлагается выбрать на свое усмотрение одну из открытых генеративных моделей на HuggingFace, донастроить его под интересующий кейс и реализовать своего бота/агента или даже сеть/цепь агентов.

Задачи:
1. Зарегистрироваться на Huggingface.
2. Получить API-ключ.
3. Получить доступ к какой-либо LLM-модели.
4. Развернуть модель локально.
Обзор big data экосистемы: хранение и обработка данных, обучение и inference, model serving
рассмотреть основные элементы современной инфраструктуры обработки больших данных;
объяснить, как аналитические продукты интегрируются с продакшен-системами.
17 декабря, 20:00 — 21:30
Highload
Этот модуль посвящен высокопроизводительным вычислениям на Python. В модуле рассматриваются особенности конкурентного и асинхронного программирования и то, как на это влияет устройство виртуальной машины языка. Также внимание уделяется превратностям написания расширений на С и вопросам профилирования кода. В качестве бонуса происходит знакомство с языком Go, который часто используется Python-программистами для решения performance-critical задач.
Профилирование производительности
проанализировать особенности архитектуры, характеристики железа;
познакомиться с методиками профилирования кода;
разобраться с профилированием памяти и ЦПУ;
познакомиться с инструментами для профилирования, предоставляемыми в Linux.
22 декабря, 20:00 — 21:30
Concurrency: многопоточное программирование и примитивы синхронизации // ДЗ
разобраться с терминологией конкурентного программирования;
рассмотреть ограничения, накладываемые виртуальной машиной на multithreading;
познакомиться с примитивами синхронизации из стандартной библиотеки.
24 декабря, 20:00 — 21:30
Домашние задания: 1
ДЗ
Memcache loader. ### Материалы для выполнения ДЗ:
[https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/4300d394dd70b540317942fe0b78b11d94330956/memcache_loader](https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/4300d394dd70b540317942fe0b78b11d94330956/memcache_loader)


*Задание*: нужно переделать однопоточную версию `memc_load.py` в более производительный вариант. Сам скрипт парсит и заливает в мемкеш поминутную выгрузку логов трекера установленных приложений. Ключом является тип и идентификатор устройства через двоеточие, значением является protobuf-сообщение.

Схематичный пример выгрузки логов можно посмотреть в файле `sample.tsv`. Но для генерации полноценных `tsv.gz` файлов с логами нужно запустить скрипт `gen_sample.py`:

```sh
# python gen_sample.py <путь сохранения файлов>

# например, для сохранения файлов в текущем каталоге
python gen_sample.py .
```

После того, как скрипт отработает, в каталоге появятся файлы:

```
$ ls -lh *.tsv.gz
-rw-r--r-- 1 s.stupnikov staff 255M 29 сен 12:09 20170929000000.tsv.gz
-rw-r--r-- 1 s.stupnikov staff 255M 29 сен 12:17 20170929000100.tsv.gz
-rw-r--r-- 1 s.stupnikov staff 255M 29 сен 12:25 20170929000200.tsv.gz

$ gunzip -c 20170929000000.tsv.gz | head -3
idfa e7e1a50c0ec2747ca56cd9e1558c0d7c 67.7835424444 -22.8044005471 7942,8519,4232,3032,4766,9283,5682,155,5779,2260,3624,1358,2432,1212,528,8182,9061,9628,2055,4821,3550,4964,6924,6737,3784,5428,6980,8137,2129,8751,3000,5495,5674,3023,818,2864,8250,768,6931,3493,3749,8053,8815,8448,8757,272,5951,2831,7186,157,1629,2021,3338,9020,6679,8679,1477,7488,3751,7399,8556,5500,5333,3873,7070,3018,2734,4273,3723,4528,4657,4014
idfa f5ae5fe6122bb20d08ff2c2ec43fb4c4 -104.68583244 -51.24448376 4877,7862,7181,6071,2107,2826,2293,3103,9433,2794,4303,7500,5637,8935,6772,2481,1614,3946,7013,690,9474,1655,9718,4862,3367,3869,4255,9431,7333,5471,3267,7439,7202,7310,7875,1468,8146,9617,4336,8747,7815
gaid 3261cf44cbe6a00839c574336fdf49f6 137.790839567 56.8403675248 7462,1115,5205,6700,865,5317,4967,2104,7993,6357,2385,8639,2306,5712,5326,9929,7781,1402,8830,1978,6443,3372,6379,5426,7847,8485,8983,1938,4809,2095,6887,2720,1074,1499,7165,4922,5969,6655,241,8738,1336,7334,465,4866,3402,634,9813,6343,2686,2214,7140,4818,92,1072,4784,2376,2086,5639,6314,9411,7888,8187,8766,7524,9002,3567,3563,360,8949,2780,8299,2460,1274,1474,3030,2221,3467,9094,9014,4475,4180,2205,481,7125,1237
```

Важно обрабатывать файлики в хронологическом порядке. В данном случае под этим имеется в виду, что после обработки нужно переименовывать файл, префиксировав имя точкой, последовательно и хронологически. Заливать же можно параллельно.

## Deadline
Задание нужно сдать через неделю. То есть ДЗ, выданное в понедельник, нужно сдать до следующего занятия в понедельник. Код, отправленный на ревью в это время, рассматривается в первом приоритете. Нарушение дедлайна (пока) не карается, пытаться сдать ДЗ можно до конца курса. Но код, отправленный с опозданием, когда по плану предполагается работа над более актуальным ДЗ, будет рассматриваться в более низком приоритете без гарантий по высокой скорости проверки.

## Обратная связь
Cтудент коммитит все необходимое в свой github/gitlab репозитарий. Далее необходимо зайти в ЛК, найти занятие, ДЗ по которому выполнялось, нажать «Чат с преподавателем» и отправить ссылку. После этого ревью и общение на тему ДЗ будет происходить в рамках этого чата.
Concurrency: процессы и межпроцессное взаимодействие (IPC)
разобраться с превратностями запуска процессов в разных ОС;
познакомиться с возможностями коммуникации процессов для выполнения общей задачи;
рассмотреть устройство основных примитивов синхронизации.
29 декабря, 20:00 — 21:30
Ускорение с помощью C: расширения
разобраться с основными принципами написания расширений на языке C;
познакомиться с управлением памятью через reference counting;
рассмотреть подход к созданию сложных объектов.
12 января, 20:00 — 21:30
Ускорение с помощью C: Cython, Pypy и FFI
разобраться с генерацией С-расширений из Python-кода с помощью Cython;
познакомиться с синтаксисом Cython;
рассмотреть область применимости PyPy;
научиться вызывать функции из уже скомпилированных приложений через ffi и ctypes/.
14 января, 20:00 — 21:30
asyncio: происхождение и основы // ДЗ
познакомиться с историей появления asyncio в Python;
разобраться с корутинами и yield from;
разобраться с futures.
19 января, 20:00 — 21:30
Домашние задания: 1
ДЗ
Crawler. Краулер обходит сайт [news.ycombinator.com](https://news.ycombinator.com/) с корня и выполняет следующие задачи:

1. Обходит **топ новостей** — первые 30 новостей на главной странице.
2. После обхода ждёт появления новых новостей в топе, которых раньше не видел.
3. Для каждой новости:
- Скачивает страницу новости.
- Скачивает все страницы по ссылкам в комментариях к новости.
- **Не ищет новые ссылки внутри скачанных страниц.**
4. Каждая новость с комментариями сохраняется в отдельной папке на диске.
5. Используемые библиотеки: стандартная библиотека Python, `aiohttp`, `aiofiles`, `BeautifulSoup`.
6. Цикл обхода запускается каждые **N секунд**.
7. Требуется Python **3.7+**.

## Дедлайн
- Задание нужно сдать через **1 неделю**.
- ДЗ, выданное в понедельник, необходимо сдать до следующего занятия в понедельник.
- Код, отправленный вовремя, рассматривается **в приоритетном порядке**.
- Опоздавшие коммиты будут рассматриваться **с меньшим приоритетом**, но допускаются для сдачи до конца курса.

## Обратная связь
1. Все изменения коммитить в свой **GitHub/GitLab репозиторий**.
2. В личном кабинете найти занятие, соответствующее ДЗ.
3. Нажать **“Чат с преподавателем”** и отправить ссылку на репозиторий.
4. Ревью и обсуждение ДЗ происходит **в чате с преподавателем**.
asyncio: event loop, внутренности async/await, низко- и высокоуровневое API
познакомиться с концепцией event loop, старым и новым синтаксисом асинхронных вызовов;
рассмотреть высоко- и низкоуровневое API asyncio;
разобраться с внутренним устройством awaitable объектов.
21 января, 20:00 — 21:30
asyncio: инструменты и лучшие практики
познакомиться с асинхронным инструментарием языка;
разобраться с тем, как корректно запускать и останавливать асинхронные сервисы;
рассмотреть примеры асинхронных библиотек для общения с БД и сетью.
26 января, 20:00 — 21:30
Golang: зачем он Python разработчику + тур по языку // ДЗ
познакомиться с синтаксисом, основными идиомами и экосистемой языка;
проанализировать область применимости языка, его сильные и слабые стороны;
провести сравнение с Python.
28 января, 20:00 — 21:30
Домашние задания: 1
ДЗ
Go memcache loader. ### Материалы для выполнения домашнего задания:
[https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/d0f98b6db1c1a56db217682a8e0286f473b81e33/go_memcache_loader](https://gitlab.com/otus.private/python-advanced-homeworks/-/tree/d0f98b6db1c1a56db217682a8e0286f473b81e33/go_memcache_loader)


*Задание*: нужно переделать однопоточную версию `memc_load.py` в более производительный вариант. Сам скрипт парсит и заливает в мемкеш поминутную выгрузку логов трекера установленных приложений. Ключом является тип и идентификатор устройства через двоеточие, значением является protobuf-сообщение.

Схематичный пример выгрузки логов можно посмотреть в файле `sample.tsv`. Но для генерации полноценных `tsv.gz` файлов с логами нужно запустить скрипт `gen_sample.py`:

```sh
# python gen_sample.py <путь сохранения файлов>

# например, для сохранения файлов в текущем каталоге
python gen_sample.py .
```

После того, как скрипт отработает, в каталоге появятся файлы:

```
$ ls -lh *.tsv.gz
-rw-r--r-- 1 s.stupnikov staff 255M 29 сен 12:09 20170929000000.tsv.gz
-rw-r--r-- 1 s.stupnikov staff 255M 29 сен 12:17 20170929000100.tsv.gz
-rw-r--r-- 1 s.stupnikov staff 255M 29 сен 12:25 20170929000200.tsv.gz

$ gunzip -c 20170929000000.tsv.gz | head -3
idfa e7e1a50c0ec2747ca56cd9e1558c0d7c 67.7835424444 -22.8044005471 7942,8519,4232,3032,4766,9283,5682,155,5779,2260,3624,1358,2432,1212,528,8182,9061,9628,2055,4821,3550,4964,6924,6737,3784,5428,6980,8137,2129,8751,3000,5495,5674,3023,818,2864,8250,768,6931,3493,3749,8053,8815,8448,8757,272,5951,2831,7186,157,1629,2021,3338,9020,6679,8679,1477,7488,3751,7399,8556,5500,5333,3873,7070,3018,2734,4273,3723,4528,4657,4014
idfa f5ae5fe6122bb20d08ff2c2ec43fb4c4 -104.68583244 -51.24448376 4877,7862,7181,6071,2107,2826,2293,3103,9433,2794,4303,7500,5637,8935,6772,2481,1614,3946,7013,690,9474,1655,9718,4862,3367,3869,4255,9431,7333,5471,3267,7439,7202,7310,7875,1468,8146,9617,4336,8747,7815
gaid 3261cf44cbe6a00839c574336fdf49f6 137.790839567 56.8403675248 7462,1115,5205,6700,865,5317,4967,2104,7993,6357,2385,8639,2306,5712,5326,9929,7781,1402,8830,1978,6443,3372,6379,5426,7847,8485,8983,1938,4809,2095,6887,2720,1074,1499,7165,4922,5969,6655,241,8738,1336,7334,465,4866,3402,634,9813,6343,2686,2214,7140,4818,92,1072,4784,2376,2086,5639,6314,9411,7888,8187,8766,7524,9002,3567,3563,360,8949,2780,8299,2460,1274,1474,3030,2221,3467,9094,9014,4475,4180,2205,481,7125,1237
```

Эти сгенерированные `tsv.gz` файлы и нужно передавать вашей программе на вход:

```
$ python memc_load.py --pattern=*.tsv.gz --dry
[2017.09.29 12:39:52] I Memc loader started with options: {'dry':True, 'log':None, 'pattern':'*.tsv.gz', 'idfa':'127.0.0.1:33013', 'dvid':'127.0.0.1:33016', 'test':False, 'adid':'127.0.0.1:33015', 'gaid':'127.0.0.1:33014'}
[2017.09.29 12:39:52] I Processing 20170929000000.tsv.gz
[2017.09.29 12:39:52] D 127.0.0.1:33013 - idfa:e7e1a50c0ec2747ca56cd9e1558c0d7c -> apps: 7942 apps: 8519 apps: 4232 apps: 3032 apps: 4766 apps: 9283 apps: 5682 apps: 155 apps: 5779 apps: 2260 apps: 3624 apps: 1358 apps: 2432 apps: 1212 apps: 528 apps: 8182 apps: 9061 apps: 9628 apps: 2055 apps: 4821 apps: 3550 apps: 4964 apps: 6924 apps: 6737 apps: 3784 apps: 5428 apps: 6980 apps: 8137 apps: 2129 apps: 8751 apps: 3000 apps: 5495 apps: 5674 apps: 3023 apps: 818 apps: 2864 apps: 8250 apps: 768 apps: 6931 apps: 3493 apps: 3749 apps: 8053 apps: 8815 apps: 8448 apps: 8757 apps: 272 apps: 5951 apps: 2831 apps: 7186 apps: 157 apps: 1629 apps: 2021 apps: 3338 apps: 9020 apps: 6679 apps: 8679 apps: 1477 apps: 7488 apps: 3751 apps: 7399 apps: 8556 apps: 5500 apps: 5333 apps: 3873 apps: 7070 apps: 3018 apps: 2734 apps: 4273 apps: 3723 apps: 4528 apps: 4657 apps: 4014 lat: 67.7835424444 lon: -22.8044005471
[2017.09.29 12:39:52] D 127.0.0.1:33013 - idfa:f5ae5fe6122bb20d08ff2c2ec43fb4c4 -> apps: 4877 apps: 7862 apps: 7181 apps: 6071 apps: 2107 apps: 2826 apps: 2293 apps: 3103 apps: 9433 apps: 2794 apps: 4303 apps: 7500 apps: 5637 apps: 8935 apps: 6772 apps: 2481 apps: 1614 apps: 3946 apps: 7013 apps: 690 apps: 9474 apps: 1655 apps: 9718 apps: 4862 apps: 3367 apps: 3869 apps: 4255 apps: 9431 apps: 7333 apps: 5471 apps: 3267 apps: 7439 apps: 7202 apps: 7310 apps: 7875 apps: 1468 apps: 8146 apps: 9617 apps: 4336 apps: 8747 apps: 7815 lat: -104.68583244 lon: -51.24448376
[2017.09.29 12:39:52] D 127.0.0.1:33014 - gaid:3261cf44cbe6a00839c574336fdf49f6 -> apps: 7462 apps: 1115 apps: 5205 apps: 6700 apps: 865 apps: 5317 apps: 4967 apps: 2104 apps: 7993 apps: 6357 apps: 2385 apps: 8639 apps: 2306 apps: 5712 apps: 5326 apps: 9929 apps: 7781 apps: 1402 apps: 8830 apps: 1978 apps: 6443 apps: 3372 apps: 6379 apps: 5426 apps: 7847 apps: 8485 apps: 8983 apps: 1938 apps: 4809 apps: 2095 apps: 6887 apps: 2720 apps: 1074 apps: 1499 apps: 7165 apps: 4922 apps: 5969 apps: 6655 apps: 241 apps: 8738 apps: 1336 apps: 7334 apps: 465 apps: 4866 apps: 3402 apps: 634 apps: 9813 apps: 6343 apps: 2686 apps: 2214 apps: 7140 apps: 4818 apps: 92 apps: 1072 apps: 4784 apps: 2376 apps: 2086 apps: 5639 apps: 6314 apps: 9411 apps: 7888 apps: 8187 apps: 8766 apps: 7524 apps: 9002 apps: 3567 apps: 3563 apps: 360 apps: 8949 apps: 2780 apps: 8299 apps: 2460 apps: 1274 apps: 1474 apps: 3030 apps: 2221 apps: 3467 apps: 9094 apps: 9014 apps: 4475 apps: 4180 apps: 2205 apps: 481 apps: 7125 apps: 1237 lat: 137.790839567 lon: 56.8403675248
```

Важно обрабатывать файлики в хронологическом порядке. В данном случае под этим имеется в виду, что после обработки нужно переименовывать файл, префиксировав имя точкой, последовательно и хронологически. Заливать же можно параллельно.


## Deadline
Задание нужно сдать через неделю. То есть ДЗ, выданное в понедельник, нужно сдать до следующего занятия в понедельник. Код, отправленный на ревью в это время, рассматривается в первом приоритете. Нарушение дедлайна (пока) не карается, пытаться сдать ДЗ можно до конца курса. Но код, отправленный с опозданием, когда по плану предполагается работа над более актуальным ДЗ, будет рассматриваться в более низком приоритете без гарантий по высокой скорости проверки.

## Обратная связь
Cтудент коммитит все необходимое в свой github/gitlab репозитарий. Далее необходимо зайти в ЛК, найти занятие, ДЗ по которому выполнялось, нажать “Чат с преподавателем” и отправить ссылку. После этого ревью и общение на тему ДЗ будет происходить в рамках этого чата.
Golang: горутины, планировщик, конкурентная обработка
познакомиться с особенностями реализации языка;
рассмотреть принципы работы с памятью;
разобраться с диспетчером горутин;
познакомиться с примерами реальных задач, решаемых с помощью Go.
2 февраля, 20:00 — 21:30
Обзор новинок и изменений из свежих версий Python
познакомиться с новшествами последних минорных версий языка;
обсудить грядущие анонсированные изменения;
разобраться с процессом миграции между версиями.
4 февраля, 20:00 — 21:30
Проектная работа
Заключительный месяц курса посвящен разработке проекта. В качестве темы выбирается то, что интересно писать студенту, и то, что потенциально можно будет потом включить в свое резюме. Участие в разработке некоего open source продукта тоже может рассматриваться в качестве выпускного проекта. При этом не обязательно закончить его за месяц. В процессе написания проекта можно получить консультации преподавателей.

Примеры тем проекта:
- система мониторинга ПК в корпоративной сети;
- свой ORM;
- web-приложение по поиску групп с целевой аудиторией в ВК;
- исследование dataset’а с визуализацией.
Выбор темы и организация проектной работы
выбрать и обсудить тему проектной работы;
спланировать работу над проектом;
ознакомиться с регламентом работы над проектом.
9 февраля, 20:00 — 21:30
Домашние задания: 1
ДЗ
Проектная работа . Тема Итоговой Проектной Работы (далее - ИПР) может являться свободной для выбора, но необходимой для согласования в чате ДЗ.

После выбора темы необходимо приступить к разработке ИПР, ориентируясь на следующие этапы жизненного цикла разработки Программного Обеспечения:

## 1. Сбор и анализ требований

Сформировать собственные требования к итоговому продукту, опционально - провести опрос среди коллег/студентов для определения потенциальной ценности для пользователей. Определить бизнес-задачу, которую будет решать проект. Итоговые требования целесообразно включить в презентацию ИПР.

## 2. Планирование

На данном этапе уточняются и формализуются ключевые цели ИПР, его границы и приоритеты. Уточняется список автоматизируемых процессов (развёртывание, миграции БД и т.д.). Выполняется первичная оценка сроков, необходимых ресурсов и интеграций. Также на данном этапе полезно проанализировать сторонние проекты, которые могут использоваться для решения подобных задач, выявить существующие практики в данном направлении и рассмотреть целесообразность их внедрения в ИПР. Результат — понятный рабочий план ИПР, с оформленными целями, приоритетами, объёмом работ и ориентировочными сроками. Итоговый рабочий план и цели целесообразно включить в презентацию ИПР.

## 3. Проектирование

На данном этапе определяется архитектура ИПР, происходит выбор используемых технологий, прорабатываются пользовательские сценарии/ программные интерфейсы и определяется, как будут работать ключевые модули. Важно учесть не только текущие требования, но и перспективу масштабирования, поддержки и безопасности (Контейнеризацию, возможности по авторизации/аутентификации, способы хранения чувствительной информации). Итоговые требования и технологии целесообразно включить в презентацию ИПР.

## 4. Разработка

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

## 5. Тестирование

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

## 6. Развёртывание

На данном этапе необходимо развернуть проект в тестовой среде (в будущем пригодной к демонстрации на защите ИПР). Необходимо предусмотреть прозрачность и документальное обеспечение процесса развёртывания (как в автоматизированном так и в ручном режиме), с использованием технологий автоматизации процесса развёртывания, непрерывной интеграции и доставки (CI/CD), контейнеризации также с механизмами периодической проверки работоспособности ИПР. Краткую и обобщённую документацию по развёртыванию целесообразно включить в презентацию ИПР.

## 7. Эксплуатация и мониторинг

На данном этапе необходимо предусмотреть реализацию инструментов, имитирующих эксплуатацию ИПР - написать примеры запросов к сервису или примеры использования функций с отображением результатов работы. Данные инструменты необходимо реализовать с учётом возможности их демонстрации в процессе защиты ИПР. Также необходимо реализовать возможность демонстрации журналов логирования, отражающих эксплуатацию ИПР в режиме отладки (Debug). Инструменты, имитирующие эксплуатацию ИПР а также получаемые сообщения подсистемы логирования целесообразно использовать на этапе защиты ИПР.

## 8. Защита Итоговой Проектной Работы

На данном этапе необходимо предоставить ссылку на репозиторий с исходным кодом проекта а также подготовить презентацию к защите ИПР в 2-х вариантах, соответствующих следующим критериям:

### 8.1. Общая презентация ИПР

Презентация, рассчитанная на выступление приблизительной длительностью 5 минут (10-20 страниц) из расчёта 2-4 страницы на каждую минуту презентационного выступления.

### 8.2. Расширенная презентация ИПР

Презентация, рассчитанная на выступление приблизительной длительностью 10 минут (20-40 страниц) из расчёта 2-4 страницы на каждую минуту презентационного выступления.

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

## Формат сдачи

Выбрана тема и закреплена.
Разработан проект и ссылка на репозиторий отправлена в "чат с преподавателем".
Разработана презентация в 2-х вариантах, в соответствии с критериями оценки.
Проект представлен на защиту.
Консультация по проектам и домашним заданиям
получить ответы на вопросы по проекту, ДЗ и по курсу.
11 февраля, 20:00 — 21:30
Защита проектных работ
защитить проект и получить рекомендации экспертов.
9 марта, 20:00 — 21:30

Преподаватель

Станислав Ступников
Руководитель отдела разработки в VK
10+ лет опыта промышленной разработки, в том числе создания и поддержания веб-приложений, инфраструктурных решений, высоконагруженных систем, data pipeline'ов и аналитических систем.

3 года научной разработки для крупных государственных заказчиков с контрактами по тематике анализа больших объемов данных. Опыт программирования на Python, Go, Lua, C, JavaScript, Perl.

Широкий круг профессиональных интересов, начиная от построения распределенных систем, заканчивая машинным обучением. Более 5 лет преподавал программирование на Python студентам МГТУ им. Н.Э. Баумана. С момента старта преподаю на курсе по СУБД в образовательном центре VK при МГТУ им. Н.Э. Баумана. 4 года преподавания курса СУБД в Технопарк Mail.Ru. Закончил МГТУ им. Н.Э. Баумана по специальности «Специалист по защите информации» в 2013 году.
Преподаватель курсов:

F.A.Q.: Наиболее часто задаваемые вопросы:

Нужно ли оплачивать обучение до Дня открытых дверей, если я хочу гарантированно попасть в группу?
Да, мы рекомендуем заранее оплатить обучение, чтобы гарантированно попасть в группу. В период проведения Дня открытых дверей резко возрастает количество желающих обучаться, поэтому может случиться так, что к окончанию Дня открытых дверей мест в группе не останется
Кто будет проводить День открытых дверей?
Проводить День открытых дверей будет преподаватель курса.
Как принять участие в Дне открытых дверей?
Для того, чтобы принять участие в Дне открытых дверей, оставьте свой e-mail в поле регистрации на мероприятие. Перед началом Дня открытых дверей мы пришлем вам ссылку, пройдя по которой, вы сможете присоединиться к вебинару.
Какие вопросы будем обсуждать на Дне открытых дверей?
На дне открытых дверей мы поговорим о проекте OTUS (о программе курса, почему мы не принимаем в группы новичков, почему учиться у нас интересно, но сложно), карьерных перспективах выпускников (почему вероятность карьерного роста у лучших студентов стремится к 100%), учебном процессе (оплатах, оценке знаний, сертификатах и прочих аспектах). Также ведущий мероприятия с радостью ответит на все ваши вопросы.