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

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

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Что выведет код с изображения ниже? №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
После нажатия Enter начнётся скачивание базового образа и выполнение инструкций. Если проект большой, это может занять какое-то время. Во время выполнения, консоль будет заблокирована от ввода, как только сборка закончится, появится курсор.


Запуск контейнера.
Финишная прямая.

Для запуска контейнера выполним команду:
docker run --name <имя_контейнера> --env-file=./.env -d <имя_образа>

Команда docker run выполняет запуск контейнера из образа.

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

Параметр --env-file определяет расположение .env-файла для передачи в систему образа переменных окружения. Это необходимо для безопасности, чтобы в контейнере не было файла.

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

В самом конце команды указывается имя созданного ранее образа.


Дополнительные команды:
- Остановка контейнера - docker stop <имя_контейнера>.
- Запуск остановленного контейнера - docker start <имя_контейнера>.
- Перезапуск контейнера - docker restart <имя_контейнера>.
- Удаление контейнера (когда он остановлен) - docker rm <имя_контейнера>.
- Удаление образа (когда удалён использующий его контейнер) - docker rmi <имя_образа>.


Заключение.
Это всё может показаться сложным, но на деле всё это достаточно быстро запоминается и дальше выполняется "на автомате".
В этом посте я показал запуск простого бота, не требующего дополнительных контейнеров, например, с БД.
Одним из следующих постов будет запуск нескольких контейнеров в одном docker compose сервисе.

Пост на сайте
Поддержать проект

#Python #Docker #Гайды #Telegram #AIOgram #Telegram-бот #Dockerfile #образ #dockerignore #контейнер
🔥7
Привет, друзья!

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

Фильм: Догмен

Год: 2023

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

https://www.kinopoisk.ru/film/4922959/
https://www.sspoisk.ru/film/4922959/

Приятного просмотра
👍3🔥3
Что выведет этот код? №12
🔥5
Вчера мы опубликовали нестандартную задачку. Для ее решения нужно знать, как работает вывод ошибок в Python. С задачей справилось всего 9% из 34 человек...Тут без объяснения никуда.


Код задачи:
my_dict = {}
try:
b = my_dict["bad"]
except Exception as e:
print(e)



Разберём задачу.
Создаём пустой словарь в переменной my_dict.

Далее создаём try-except конструкцию.

Внутри блока try в переменную b пытаемся получить значение из словаря по ключу "bad".

В блоке except "отлавливаем" общее исключение Exception, присваивая ему имя e, и выводим его в терминал.


Мы получили ошибку!
Это было довольно предсказуемо, потому что по ключу "bad" в наш словарь ничего не записывалось. Следовательно мы вправе ожидать стандартный KeyError. Но почему в терминале вывелось только слово bad?

Стандартное сообщение об ошибке содержит в себе класс ошибки и значение, например:
KeyError: 'bad'


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

Чтобы вывести само стандартное сообщение об ошибке, можно обратиться к dunder-методу __repr__() объекта, который мы записали в переменную e:
my_dict = {}  
try:
b = my_dict["bad"]
except Exception as e:
print(e.__repr__())

# KeyError('bad')


Для вывода трейсбека (сообщение об ошибке, включающее в себя путь до всех файлов, которые участвуют в выполнении команды, вызвавшей ошибку), можно воспользоваться встроенным модулем traceback, например:
import traceback  

my_dict = {}
try:
b = my_dict["bad"]
except Exception:
print(traceback.format_exc())

>>> Traceback (most recent call last):
>>> File "C:\...\123.py", line 5, in <module>
>>> b = my_dict["bad"]
>>> ~~~~~~~^^^^^^^
>>> KeyError: 'bad'



Заключение.
Ошибки в Python – обширная и полезная тема. Знание того, как работают ошибки, не только позволит их не совершать, но и умело их обрабатывать, а также, что немаловажно, анализировать трейсбек и сразу распознавать проблемные места... Но это уже тема для отдельного поста 😉
🔥6👍1
Всем привет!

Сегодня в 18 часов (по МСК) на YouTube-канале будет стрим.

Стрим скорее экспериментальный, посмотреть и попробовать.

На стриме начну писать Telegram-бота для управления сервером. А также общаться с вами (если кто-то придёт конечно).

Надеюсь тапок в мою сторону не прилетит)), а если понравится, то будет продолжать.

Ссылка на канал: https://www.youtube.com/@codeonanapkin
🔥6
😱😱😱

Волнительно) Первый стрим закончился. Сделали, так сказать "базу". Развивать и улучшать можно будет дальше, больше и лучше.

Надо продумать идеи для развития и улучшения. Посмотреть как он будет себя чувствовать на сервере и так далее.

Напишите ваши комментарии, критику и отзывы от первого стрима.

Запись доступна тут: https://youtube.com/live/ALB5l5sCrx8?feature=share
Исходный код залил на свой git. Доступ к репозиторию для подписчиков на Boosty : https://boosty.to/prodream/posts/889983cd-6a8b-4741-9bb5-09f920ebf89c
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Разворачивание Django-проекта на Replit
Автор: Иван Ашихмин

В одном из прошлых постов я рассказал о том, как развернуть Django-проект на бесплатном сервисе PythonAnyWhere. В этом посте поговорим о другом сервисе, который знаком многим - Replit.

Replit - это онлайн IDE для разных языков программирования. Помимо онлайн интерпретатора, он также позволяет размещать у себя небольшие проекты. Естественно, с ограничениями, но, как и было сказано ранее, этот способ подойдёт для демонстрации проекта, а не для рабочего использования.
🔥6