Код на салфетке
2.24K subscribers
750 photos
15 videos
2 files
793 links
Канал для тех, кому интересно программирование на Python и не только.

Сайт: https://pressanybutton.ru/
Чат: https://t.iss.one/+Li2vbxfWo0Q4ZDk6
Заметки автора: @writeanynotes

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Задача прошлой недели и вчерашняя задача похожи. И там, и там вся суть в поведении изменяемых типов данных... И капелька внимательности.

В викторине приняли участие 43 человека. Верный ответ оказался самым популярным! Верно ответило 16 человек, поздравляю. Вторым по популярности был третий ответ , набравший 32% ответов. Следом за ним идёт первый ответ с 26% ответов.


Код задачи:
def add_to_list(item, lst=[]):
lst.append(item)
return lst


list_a = add_to_list(1)
list_b = add_to_list(2, [])
list_c = add_to_list(3)
list_d = add_to_list(4, [])

print(list_c)



Разберём задачу.
В самом начале создаём функцию add_to_list, принимающую два аргумента:
- Обязательный аргумент item.
- Необязательный аргумент lst. В качестве значения по умолчанию установлен пустой список.

В теле функции мы добавляем в список lst значение переменной item. Затем возвращаем список.

Достаточно простая функция с несложной логикой.
После функции инициализируем четыре переменные:
1. list_a - в этой переменной вызываем функцию передав в неё только число 1.
2. list_b - в этой переменной вызываем функцию, передав в неё число 2 и пустой список.
3. list_c - в этой переменной также вызываем функцию с одним аргументом 3.
4. list_d - в этой переменной вызываем функцию и передаём число 4 и пустой список.

В конце выводим значение переменной list_c.

Что могло пойти не так?
Всё банально и просто. Python – интерпретируемый язык. Это означает, что он сперва читает файл, а потом выполняет его построчно. Т.к. функции не сразу начинают что-то делать, он их читает, инициализирует и дальше идёт по тексту пока объект функции не понадобится.

Именно так происходит и тут. Интерпретатор доходит до add_to_list и видит, что у него в качестве значения аргумента lst по умолчанию указан пустой список и создаёт его в памяти. Назовём его lst_0. Это важный момент. Конкретный список, записанный в переменную lst_0 , до конца исполнения кода останется тем самым списком по умолчанию в необязательном аргументе функции, сколько бы раз эта функция ни вызывалась дальше. Это значит, что в нём будут сохраняться результаты всех предыдущих изменений. Подробнее о том, как ведут себя изменяемые и неизменяемые типы данных, можно прочесть в [нашем посте на эту тему](https://t.iss.one/press_any_button/356).

Далее мы создаём четыре переменные:
1. list_a - передаём только число 1. В результате lst_0 имеет вид [1].
2. list_b - передаём число 2 и пустой список. Это новый список, назовём его lst_b и он имеет вид [2].
3. list_c - передаём только число 3. Поскольку не был передан список, то используется ранее созданный lst_0. В результате он имеет вид [1, 3].
4. list_d - передаём число 4 и пустой список. Это ещё один новый список, назовём его lst_d. Он имеет вид [4].

В результате у нас есть три списка:
- lst_0 = [1, 3]
- lst_b = [2]
- lst_d = [4]


Заключение.
Будьте аккуратны с использованием изменяемых типов данных в качестве значений по умолчанию. Это может сыграть с вами злую шутку в самый неподходящий момент.
👍5🔥5
С днём рождения, Андрей!
Автор: Иван Ашихмин

Сегодня 13 февраля 2024 года.. Вы наверняка спросите: "И что такого особенного в этом дне?". А я вам сейчас расскажу!!!

- День Дарвина (международный)
- День прокладывания тропинок
- День безумного желудка
- День объятий (Индия)
- День очистки компьютера (США)

А ещё, сегодня День Рождения у нашего главреда (не путать с главным вредителем, хотя это звание ему очень подходит, даже беря в расчет его характер). Так давайте все дружно поздравим его с Днём Рождения!!!


Поздравление от меня:
Когда у нас начался Python в основном блоке обучения, тогда-то я и познакомился с Андреем. Я сразу приметил его острый ум и нестандартный подход к решению задач. Затем мне довелось с ним и Владимиром поработать в команде, честно, тогда я считал себя самым глупым в нашей троице. А потом пошла Java и куча скучных курсов, от которых у Андрея пропал интерес к учёбе...
🎉7
Не так давно Андрей снова увлёкся питоном и программированием. Присоединился к некому проекту, пишет посты для канала и радует вас нестандартными задачками (которые я с первого раза так и не отгадывал).
В связи со всем вышесказанным хочу пожелать Андрею следующее:
Самого главного - здоровья твоей маленькой дочурке. Ведь дети, это прекрасно.
Ну и тебе тоже здоровья, а то как без него о дочурке-то заботиться?
Хочу пожелать или даже высказать надежу, что ты не бросишь программирование, а продолжишь учиться, развиваться и станешь отличным специалистом. Оставайся всё таким же весёлым, забавным, а порой невыносимым. И просто радуйся каждому дню.


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

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

И так, первая задача:
Кто шефа - правая рука? 
Тут знают все наверняка,
Кто машет тапком тут и там -
Ты угадай по "двум словам".

Она - угроза всем, но скажет...
Что всех поймёт и всем подскажет.
И кофе от неё не жди
Тут лишь задачи впереди...



Задача выдана, Андрей?
Чего же ты ждёшь?!
Ищи ответ и не робей,
все ждут, когда ты путь начнёшь!
Как только выяснишь Хранителя,
Пиши ему не медля!
И оказавшись в его обители,
Реши задачу разуму внемля!

Пост на сайте

#Код_на_салфетке #Код_в_мешке #День_рождения #Андрей #Главный_редактор
🎉6
Андрей долго плутал в лабиринте в поисках заветной двери, ведущей к первому Хранителю. Он знал, что первый Хранитель - это секретарь и вглядывался в символы на дверях, но всё было не то, пока не наткнулся на розовую дверцу украшенную кофейными зёрнами и тогда он понял - это была та самая дверь...


Кристина:
Поздравляю, ты открыл первую дверь! Проходи, располагайся, будешь кофе?..

Андрей:
На овсяном молоке, пожалуйста.

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


Кристина:
А теперь у меня для тебя загадка, разгадав которую ты получишь ключ и направление к следующему Хранителю. Приступим..

На нашем канале есть много разных людей, из них 5 человек изъявили желание поучаствовать в твоём поздравлении: 4 программиста и 1 музыкант. Предположим, что они встали в ряд. У них у всех разные имена. Каждый занимается своим направлением. Каждый из них пьёт свой напиток, предпочитает свое блюдо и содеpжит своё домашнее животное. Определи, кто из них содеpжит рыбок, следующий ключ находится у него/неё?

1. Владимир занимается мобильной разработкой.
2. У fullstack есть черепашка.
3. Мобильщик пьёт чай.
4. Артур стоит левее Вани, но стоят они рядом, разглагольствуют.
5. Артур пьёт кофе.
6. У того, кто ест суши, есть попугай.
7. Настя ест лазанью.
8. Третьим стоит тот, кто пьёт молоко.
9. Настя стоит первая.
10. Программист, который ест шашлык, стоит pядом с хозяином кошки.
11. Тот, кто содеpжит собаку, стоит pядом с тем, кто ест лазанью.
12. Тот, кто ест мармелад, пьёт пиво.
13. Артур любит пиццу.
14. Настя стоит pядом с мобильщиком.
15. У программиста, который ест шашлык, есть сосед, который пьёт водy.
16. Рядом с Владимиром стоит Backend-разработчик
17. QA любит кофе
18. Толик музыкант

Андрей:
Надеюсь, Артур не мой кофе пьет.
(Это не ответ)
Так, я беру пенсне, листик и бумажку. К утру будет ответ)
Попытки решить задачу на листе бумаги на который претендует дочка...
Артур
Хорошо, что не Толик. А то он суши любит…

Кристина:
Поздравляю тебя с верным ответом, теперь ты знаешь куда тебе идти дальше. Удачи.
🔥31😁1
Успешно ответив на такую нетривиальную задачку, Андрей вернулся в лабиринт. Как только он переступил порог, дверь резко захлопнулась за ним, забирая с собой ароматы кофе... И он мог поклястся, что слышал зловещий смех... Он стоял и обдумывал произошедшее - "После первого раза стало проще", подумал он и начал понимать правила игры. Блуждая по коридорам, вглядываясь в двери он заметил, что на одной из дверей шелушится на ветру видеоплёнка, а по центру приколочена большая хлопушка. Вот она" - подумал он и без капли сомнений шагнул за порог.


Андрей:
Салям алейкум, брат!
Я пришел к тебе в поисках рыбок)

Артур:
Поздравляю, ты открыл вторую дверь! Проходи, располагайся, не желаешь посмотреть со мной фильм, прежде чем мы приступим к задаче?..

Андрей:
Множество историй, коль желаешь, посмотрю.

Артур:
С днём рождения! Пусть этот день будет для тебя особенным, полным радости и счастья. Пусть исполнятся все твои мечты и желания, а каждый следующий год приносит только благополучие и успех.

Андрей:
Спасибо!

Артур:
А теперь у меня для тебя загадка, разгадав которую ты получишь ключ и направление к следующему Хранителю. Приступим..

Первая загадка:
В комнате 53 человека. Каждый из них здоровается с каждым другим. Сколько рукопожатий произойдет?


Андрей:
А вы вообще придумали, что делать, если я ошибусь?)
Надеюсь, придумали.
1378 у меня получилось.
Воть

Артур:
Верно!

Вторая загадка:
В комнате есть три лампочки и три выключателя, каждый из которых соответствует одной лампочке. Вначале все лампочки выключены. Ты находишься за дверью и можешь войти в комнату только один раз. Как определить, к какому выключателю относится каждая лампочка, если ты не видишь, какие лампочки горят, а какие нет?


Андрей:
Сначала включить одну и подождать несколько минут. Выключить и включить вторую. Войти в комнату. Которая горит - включается вторым выключателем. Которая теплая из оставшихся - первым. А холодная и негорящая - третьим.

Артур:
Верно!

Третья загадка:
Кто в чате музыкой нас развлекает? 
Клиентов хает только в путь!
На синтезаторе для всех играет,
Голосовые шлёт и там и тут!


Андрей:
Это разные люди.
Голосовые - Настя шлет. А музыку - Ваня. Клиентов вообще все хают. А синтезатор - в душе не знаю. Эту загадку сложнее гуглить.

Артур:
Ахахах). Подумай ещё. Эти качества умещаются в одном человеке и ты его знаешь

Андрей:
Сначала я подумал, что Игорь Николаев. Но он не в чате.
Анатолий, палучаецца.

Артур:
Верно!🥳

Артур:
Поздравляю тебя с верным ответом, теперь ты знаешь куда тебе идти дальше. Удачи.

Андрей:
Ну всё, я к нему тогда. Рахмат!

Артур:
Удачи)
🔥3
"Музыка!" - воскликнул Андрей. "Я видел дверь со скрипичным ключом!" - продолжал он. Уверенно повернулся назад и быстрым темпом направился обратно. "Где-то здесь..." - бормотал Андрей, разглядывая двери и внезапно для себя, уловил он тонкие звуки фортепьяно... Идя на звук, он становился всё чётче и вот она, дверь со скрипичным ключом. Распахнув её, его обдало сильной звуковой волной. На секунду, он даже подумал, что оглох, ковыряя пальцем в ухе, но деваться было некуда, нужно было входить.


Андрей:
Привет, Анатолий! Я к тебе за вопросом.

Анатолий:
Доброе утро путник! Дай мне секунду я где то потерял свиток
Гром и шорох из под шкафа с нотными тетрадями

Андрей:
Пригласи меня на ужин дружелюбным жестом.

Анатолий:
Поздравляю, ты открыл третью дверь! Проходи, располагайся, послушаем музыку и приступим, хорошо?..
https://music.yandex.ru/album/5788622/track/137670?utm_medium=copy_link

Андрей:
Погнали

Анатолий:
И так Андрэа, поздравляю тебя с твоим днём рождения, желаю всех благ, здоровья особенно, а дальше всё будет, что бы твои цели все были достигнуты, тост 🥂 за что? Зае**сь! Вот что бы и в жизни так было!

Андрей:
Благодарю!

Анатолий:
А теперь у меня для тебя загадка, разгадав которую ты получишь ключ и направление к следующему Хранителю. Приступим..

Андрей:
Агась

Первая загадка:
Довольно старая песня про художника, который полюбил одну девчонку, так полюбил, что купил очень очень много цветов, подумай хорошо, время есть

Андрей:
Так миллион алых роз

Анатолий:
Верно!

Вторая загадка:
А теперь присаживайся, я сыграю тебе мелодию, ну а ты попробуй угадать
звуки музыки

Андрей:
Ну это точно не Агутин…

Анатолий:
Точно нет 😄
У тебя есть 3 подсказки которыми ты можешь воспользоваться

Андрей:
Да я слышу, там на фоне кто-то пытается подсказывать.

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

Андрей:
Зе ласт оф ас, получается?

Анатолий:
Умничка! Идём дальше

Третья загадка:
Назови имя человека у которого есть своя рок группа, но по мимо этого он еще и снялся в паре фильмов, представь себе! Музыкант и Актёр, две крайности одной сущности 😱

Андрей:
Таких не один) Джаред Лето, например, Киану Ривз, Виктор Цой. Да даже Сергей Паук Троицкий!

Анатолий:
Таак, так так, но только один правильный ответ

Андрей:
И как я должен выбрать среди такой замечательной компании одного человека?

Анатолий:
Нууу, ой слушай я проголодался, хочу котлетку, о да!

Андрей:
Джаред Котлето?

Анатолий:
Ееессс! Только никому не говори 🤫

Четвёртая загадка:
Смотри какое красивое у меня пианино, только вот сколько оно имеет клавиш? У меня 77 а по стандарту?

Андрей:
Только не говори, что 300))
88

Анатолий:
Там шутка про тракториста? 😁

Андрей:
Её в печать не пропустят)

Анатолий:
Именно, да, ты прав, 88 клавиш!

Андрей:
И 14 аккордов, видимо.

Анатолий:
А теперь последняя загадка 🤔

Пятая загадка:
Ты же знаешь самого быстроговорящего армянина в роцк-культуре?

Андрей:
Серж

Анатолий:
А полностью?

Андрей:
Танкян!

Анатолий:
Дааа!! Я и половины не понимаю что он поёт 😁

Андрей:
Половины)

Анатолий:
И так дорогой путник я тебя поздравляю с верным ответом, следующий хранитель - Настя. Удачи 🍀
🔥4
Музыкальная загадка
🔥3👻1
Андрей вышел из музыкальной комнаты, "что-то я устал" - подумал он, но впереди ещё была половина пути. Анатолий дал ему подсказку, что следующий хранитель находится в тёмной части лабиринта и что бы он был осторожен там. Андрей направился в путь. Тут и так темно, но заходя дальше становилось не просто темнее, а мрачнее. Повсюду были записки с кодом, на которых чётко виднелась одна надпись - "USER"... И он увидел дверь, всю исписанную кодом, вокруг которой висели предупреждающие таблички, одна из низ гласила "HTMLщикам вход ВОСПРЕЩЁН!!!". Деваться было некуда, он сделал глубокий вдох и переступил порог.


Андрей:
Настя, доброе утро)

Анастасия:
Привет) Поздравляю ты открыл 4-ю дверь! Проходи располагайся, нас заждался юзер, покодим и перейдем к задачке?

Андрей:
Юзера нельзя заставлять ждать!

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

Шифр: Юшсракёхц Вэмъхясши йяы Ошмрхщхэ

Анастасия:
А пока ты отгадываешь загадку... Поздравляю тебя с Днем рождения) И желаю оставаться таким же крутым и с таким же убойным чувством юмора! Конечно же найти работу мечты и получить классный оффер 🥳

Андрей:
Следующий хранитель - это Владимир?

Анастасия:
Точно ты угадал)) Причем очень быстро

Андрей:
А юзер где? Или это Владимир?!

Анастасия:
Мы с юзером сегодня попробуем еше разок залить котикокфф на сервак

Андрей:
Мне сунуться к Владимиру?)
Или это вообще город имеется в виду? Мне пригодится Гугл.Мэпс?

Анастасия:
Ага к Владимиру)) Город это даже для нас слишком жестоко))

Андрей:
Мерси!

Анастасия:
Приходи еще юзер один скучает )
🔥2😱2
Приетствую, друзья!

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

Фильм: Мост в Терабитию

Год: 2006

Надежды ученика пятого класса Джесса Аарона стать самым быстрым бегуном в классе разбились после того, как новичок Лесли Берк одержала победу в соревнованиях. Оснований для враждебности по отношению друг к друг у Джесса и Лесли более чем достаточно, и тем не менее между ними завязывается дружба. Как тут не подружиться, если приходится быть королем и королевой в обнаруженном в лесу волшебном царстве?

https://www.sspoisk.ru/film/78753/

Приятного просмотра
👍2
Что выведет код с изображения ниже? №10
Anonymous Quiz
30%
TypeError
23%
(1, 5, 3, 4)
17%
1 TypeError
31%
6 TypeError
👍1🔥1
Что выведет этот код? №10
Вчера мы опубликовали десятую задачу из рубрики "Что выведет данный код?". Задача в этот раз была проще предыдущих и скрывала в себе всего лишь один подвох, о котором часто забывают.

В викторине приняло участие 60 человек!
Верный ответ - 6 TypeError стал самым популярным с 35% голосов, это 21 человек.
На втором месте ответ - TypeError с 25%, а на третьем ответ - (1, 5, 3, 4), набравший 23% голосов.


Код задачи:
t1 = (1)
t2 = (3, 4)
t1 += 5

print(t1)
print(t1 + t2)



Разберём задачу.
Создаём две переменные:
- t1 - в которую помещаем число пять в скобках.
- t2 - в которую помещаем кортеж, состоящий из чисел 3 и 4.

Далее к переменной t1 прибавляем число пять.

Затем в два принта выводим значение переменной t1 и произведение значений переменных t1 и t2.


Что могло пойти не так?
Я думаю, что вы уже в прошлом блоке догадались, что пошло не так.

Начнём с переменной t1. В коде число 1 мы обернули в скобки, которые....ничего с ним не делают. В Python круглые скобки вокруг единственного объекта никак не изменяют сам этот объект. Для того, чтобы значения в скобках стали кортежем, необходима как минимум одна запятая, например t1 = (1,). То есть по сути в первой строке задачи мы можем убрать скобки, не изменив смысла написанного. Мы просто записали целое число 1 в переменную t1, и вот что у нас по сути получилось: t1 = 1. Поэтому дальше, добавляя 5, мы увеличили число в переменной t1 до 6. Те, кто в этом месте подумал, что мы попытались что-то прибавить к кортежу, выбрали ответ TypeError, потому что к кортеж с числом конкатенировать нельзя. Но, как мы теперь понимаем, в t1 изначально никакого кортежа не было, поэтому print просто выведет получившееся число 6 на печать.

А вот во втором случае "прибавить" число в t1 к кортежу в t2 не получится по причине, которую мы обозначали выше: кортеж невозможно конкатенировать с числом. Конкатенация разных типов данных в большинстве случаев вообще невозможна. Список нельзя конкатенировать с числом, кортеж - со строкой и так далее. Бывают и исключения: например, числа с плавающей точкой (float) можно складывать с целыми числами (int). Но в целом для конкатенации объектов разных классов необходимо прописывать механизмы конкатенации в самих этих классах (как правило, речь о переопределении dunder-метода __add__). Но об этом мы как-нибудь поговорим отдельно.
🔥11
Привет всем!

Вжух, и снова пятница, друзья! Отложите работу в сторону. Тащите еду и напитки. Запускайте наш сегодняшний фильм. Усаживайтесь поудобнее и наслаждайтесь просмотром.

Фильм: Бёрдмен

Год: 2014

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

https://www.sspoisk.ru/film/722827/

Приятного просмотра
🔥6
Что выведет код с изображения ниже? №11
Anonymous Quiz
15%
[2]
13%
[2, 3, 5]
15%
[2, 4, 5]
58%
Ничего из перечисленного выше.
🔥6👍1🤔1🦄1
Что выведет этот код? №11
🔥5👍4🤔1
Вчера мы опубликовали задачку, которая в своей основе достаточно проста, но "соль" скрыта в её написании. И судя по доле верных ответов в 61%, она не вызвала трудностей у большей части читателей. Однако, разобрать её всё равно стоит.


Код задачи:
i = 2
x = []

while i <= 5:
x.append(i) if i % 2 != 0 or len(x) < 2 else x.pop()
i += 1

print(x)



Разберём задачу.
Создаём две переменные:
- i - обыкновенный "счётчик", который устанавливаем в значение 2.
- x - пустой список.

Далее запускаем цикл while с условием, что он будет работать пока значение нашего счётчика i меньше или равно пяти.

В теле цикла делаем условие - если значение счётчика нечётное ИЛИ длинна списка x меньше двух, то мы добавляем текущее значение счётчика в список.
Иначе мы убираем из списка последний элемент.
После этого в любом случае увеличиваем счётчик на единицу.

В конце выводим список в консоль.

Какой ответ верный?
Из предложенных вариантов, верный ответ - "ничего из перечисленного выше".
Это тоже была своего рода уловка =)

Верный ответ будет - [2, 5]

Основная сложность могла возникнуть из-за написания, поскольку условие написано не в виде классического блока if-else, а в виде тернарного оператора <действие> if <условие> else <действие>.

Разберём последовательность действий в цикле:
1. i=2, x=[]. Проверяем 2 % 2 != 0 - нет, len([]) < 2 - да. Добавляем 2 в список.
2. i=3, x=[2]. Проверяем 3 % 2 != 0 - да, второе условие не проверяется, т.к. первое True. Добавляем 3 в список.
3. i=4, x=[2, 3]. Проверяем 4 % 2 != 0 - нет, len([2, 3]) < 2 - нет. Второе условие False, поскольку 2 не меньше двух, а 2 равно 2. Удаляем последний элемент из списка.
4. i=5, x=[2]. Проверяем 5 % 2 != 0 - да, второе условие игнорируем. Добавляем 5 в список.
5. Выводим x в консоль.


Заключение.
Вот такая вот интересная задачка. В ней нет ничего сложного, но иногда трудно ориентироваться в тернарных операторах, если они насыщены условиями. Помните про dzen python - явное лучше неявного. Тернарные операторы полезны, если они считываются с первого раза, но когда для их понимания необходимо строить "карту" в голове - лучше их избегать.
👍6🔥2
Приветствую.

Изначально данный канал задумывался не только как посты с гайдами, теорией и другими полезными материалами, но и мой "личный блог", однако сейчас это не совсем впишется в тематику канала и будет тут не к месту.

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

Если вам интересно, то милости прошу на канал: https://t.iss.one/writeanynotes
🔥5🖕3😱2
Docker 7. Разворачивание Telegram-бота в Docker на VPS
Автор: Иван Ашихмин

Следующий шаг после (или даже в процессе) разработки какого-либо проекта – разворачивание (deploy) на сервере. Для этого будем использовать Docker.

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

Именно для этого есть Docker. Он упрощает разворачивание проектов на сервере, позволяет контролировать требуемые проекту зависимости и, что пригодится нам в будущем, организует для контейнеров локальную сеть, позволяющую контейнерам общаться, не выходя в интернет, снижая тем самым задержки.
🔥4
Как установить Docker на Linux, я писал в посте "Docker 2.2 Установка Docker на Linux", но создать контейнер можно и в Windows. Как установить Docker на Windows, я описывал в постах "Docker 1. Подготовка Windows" и "Docker 2.1 Установка Docker Desktop на Windows".

Для разворачивания бота нам необходимо будет проделать следующие действия:
1. Подготовить Telegram-бота, а именно сделать получение токена и других конфиденциальных данных из переменных окружения вместо прописывания их в коде. Как создать .env-файл описано в посте "AIOgram3 17. Подготовка к разворачиванию на сервере".
2. Создать Dockerfile - специальный файл, необходимый для создания Docker-образа.
3. Отправить файлы на сервер.
4. Запустить бота.


Dockerfile.
Первый пункт списка был выполнен в другом посте, поэтому переходим сразу ко второму.

В корневой директории создадим файл с именем Dockerfile. Именно так: без расширения, в одно слово.

В этом файле описываются инструкции, которые выполняет Docker в момент создания образа.

У нас будет шесть инструкций:
1. Выбор базового образа.
2. Определение рабочей директории.
3. Копирование файла requirements.txt.
4. Выполнение обновления pip и установки зависимостей.
5. Копирование файлов проекта.
6. Выполнение команды запуска проекта.


Что такое инструкции?
Инструкции в Dockerfile – это команды, которые определяют шаги создания образа Docker. Каждая инструкция в Dockerfile представляет собой отдельную команду, которая выполняется последовательно при построении образа.

Инструкции пишутся следующим образом:
ИНСТРУКЦИЯ параметры_инструцкии


Например, инструкция FROM с названием образа:
FROM python:3.11


Инструкций в Dockerfile достаточно много. Прочитать подробнее можно в документации: https://docs.docker.com/reference/dockerfile/

Обратите внимание на один момент. Docker-образ создаётся из последовательно выполняемых инструкций. Каждая инструкция создаёт отдельный слой образа. Иногда выгоднее объединять инструкции одного типа вместе для уменьшения количества слоёв, а следовательно и размера образа.


Наши инструкции.
Первой инструкцией будет - FROM. Данная инструкция определяет используемый базовый образ. На основе него и будут выполняться дальнейшие инструкции.
Для нашего бота будем использовать образ python:3.11-slim, где python - название образа, а 3.11-slim его "тег" в данном случае определяющий версию. Также обратите внимание на slim. Часто у готовых образов имеется "полная версия" и "упрощённые". У python есть три основные версии, это:
- 3.11 - полная версия Python, в данном случае конкретной версии 3.11. Размер образа, примерно, 360 МБ.
- 3.11-slim - упрощённая версия Python, без части стандартной библиотеки. Размер образа, примерно, 47 МБ.
- 3.11-alpine - самая "лёгкая" версия основанная на alpine linux. Размер образа, примерно, 18 МБ.
🔥5
Выбор версии Python остаётся за вами, но имейте в виду, что не весь код будет хорошо себя чувствовать на "облегчённых" версиях.

Второй инструкцией будет - WORKDIR. Она определяет директорию относительно корня файловой системы, в которой будет выполняться проект. В моём случае это /code. Вы можете выбрать другую. Рекомендуется использовать рабочую директорию в Docker-образе.

Третья инструкция COPY. Как понятно из названия, она копирует что-то внутрь образа. В нашем случае на этом шаге мы копируем файл requirements.txt внутрь директории /code.

Четвёртая инструкция, RUN, запускает выполнение команды внутри образа. В нашем случае, это комбинированная при помощи &amp;&amp; команда. Сперва мы обновляем pip, а затем устанавливаем необходимые зависимости для проекта.

Пятая инструкция, как и третья - COPY. В данном случае мы копируем всё из директории с Dockerfile внутрь директории /code.

И последняя, шестая, инструкция – это CMD. Данная инструкция выполняет указанную команду при запуске контейнера, основанного на этом образе. Нам необходимо выполнить команду python ./main.py, но просто так мы её написать не можем. Команды необходимо писать в списке строк, разделяя всю команду по пробелам - [ "python", "./main.py" ].


Код Dockerfile:
FROM python:3.11-slim  

WORKDIR /code

COPY requirements.txt /code
RUN pip install --upgrade pip &amp;&amp; pip install -r requirements.txt

COPY . /code

CMD [ "python", "./main.py" ]



Файл .dockerignore
Перед тем, как перейдём к загрузке файлов на сервер, необходимо позаботиться о том, чтобы в наш образ при копировании не попадали ненужные файлы. Для этого нужно создать .dockerignore-файл. Он по аналогии с .gitingore-файлом будет отсеивать то, что в нём прописано.
.idea  
.vscode
.git
**/__pycache__
*.pyc
.env


Первые две строки фильтруют директории с файлами IDE.
Третья убирает директорию git, если у вас подключена система контроля версий.
Четвёртая и пятая строчки фильтруют от файлов кэша Python.
Последняя строчка не пропускает в образ ваш .env-файл.


Загрузка файлов на сервер.
В посте "Разворачивание Django-проекта на PythonAnyWhere" я рассказывал о способе загрузки через git-репозиторий. Для себя я использую иной вариант - sftp.

sftp - это протокол передачи файлов по SSH. Есть различные программы, позволяющие подключиться к серверу и отправить туда файлы. Я рекомендую программу xftp, она бесплатна для частного использования.
Скачать можно на сайте: https://www.netsarang.com/ru/xftp/

Подключаемся к серверу по SSH, используя для передачи git-репозиторий или по sftp для прямой передачи файлов на сервер.


Создание образа.
После того как файлы залиты на сервер, настало время создать образ.

Подключаемся к серверу по SSH. Для этого можно использовать различные программы. на подобии PyTTY или xshell, но мне удобнее стандартный PowerShell, обновлённый до 7-й версии.

Переходим в директорию с проектом, используя команду cd.

Для создания образа выполняем следующую команду:
docker build -t <имя_образа> .


Командой docker build мы вызываем сборку образа, далее параметром -t указываем имя образа, последняя точка означает, что Dockerfile для сборки находится в этой же директории.
🔥3