Код на салфетке
2.22K subscribers
745 photos
14 videos
2 files
788 links
Канал для тех, кому интересно программирование на Python и не только.

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

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Напиши свой ответ в комментариях. Если ты знаешь правильный ответ, то мы будем рады видеть тебя на нашем контесте.
🔥2🤔1
Вчера мы опубликовали задачу, в которой асинхронное приложение одновременно выполняет две задачи: читает текстовые файлы и запускает программу, использующую этот текст. Однако, несмотря на параллельное выполнение задач, возникает проблема с тем, что текст может быть недоступен в момент его обработки.

Задача:
У вас есть асинхронное приложение, которое запускает программу и одновременно читает текстовые файлы с диска. Программа должна использовать текст, который подгружается при старте. Две задачи запускаются параллельно: одна читает текстовые файлы, другая — запускает программу, которая использует этот текст.

Посмотрите на код ниже и определите, что будет выведено:

import asyncio

texts = []


async def read_files() -> None:
await asyncio.sleep(2)
texts.append("Текст из файла")


async def process_text() -> None:
if not texts:
raise ValueError("Нет текста для обработки")
print(f"Использую: {texts[0]}")


async def start_app() -> None:
await process_text()


async def main() -> None:
await asyncio.gather(read_files(), start_app())


asyncio.run(main())



Разбор кода:
1. Объявление глобального списка `texts`:
- В начале программы объявляется пустой список texts, который позже будет заполняться текстом из файла.
- Он используется для хранения подгруженных данных.

2. Функция `read_files`:
- Эта асинхронная функция имитирует чтение файла, используя await asyncio.sleep(2) для создания задержки в 2 секунды.
- После ожидания в список texts добавляется строка "Текст из файла". Фактически, эта функция наполняет список, который должен использоваться в программе.

3. Функция `process_text`:
- Эта функция пытается использовать текст из глобального списка texts.
- Она проверяет, пуст ли список: if not texts:. Если в момент проверки списка он пуст, вызывается исключение ValueError("Нет текста для обработки").
- Если же в списке есть данные, программа выводит сообщение с текстом: Использую: {texts[0]}.

4. Функция `start_app`:
- Эта функция просто вызывает process_text, чтобы обработать текст.

5. Функция `main`:
- В функции main с помощью asyncio.gather одновременно запускаются две задачи:
- read_files() — задача чтения файла, которая длится 2 секунды.
- start_app() — задача, которая сразу же пытается обработать текст из списка texts.


Почему возникает ошибка:

Когда запускаются обе задачи с помощью asyncio.gather, они выполняются параллельно. Однако здесь есть ключевой момент: задача чтения файла (read_files) содержит задержку в 2 секунды. В то время как текст ещё не загружен, функция start_app() немедленно вызывает process_text, который пытается получить текст из списка texts. Но список в этот момент ещё пуст, так как данные ещё не успели подгрузиться. Это приводит к тому, что проверка if not texts: срабатывает, и выбрасывается исключение ValueError: Нет текста для обработки.

Итог:
Программа завершится с ошибкой:
ValueError: Нет текста для обработки



Как это исправить:

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

async def main() -> None:
await read_files() # Ждём завершения чтения файла
await start_app() # Только после этого запускаем обработку


Теперь текст гарантированно будет загружен перед его использованием, и программа завершится успешно:
Использую: Текст из файла
👍2🔥2
Реальная история

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

Однако я не учёл, что первое сообщение, которое бот отправляет при запуске, — это уведомление администратору о том, что бот запущен. Это сообщение, как и другие, находилось в YAML-файлах. В результате бот стартовал, пытался отправить уведомление, но не мог, потому что файлы ещё не были прочитаны.

Вывод: хранить текстовые файлы удобно для пользовательских сообщений, но критически важные сервисные сообщения лучше хранить непосредственно в коде. Это позволяет избежать ситуации, когда программа пытается использовать данные, которые ещё не успели загрузиться.
🔥4🤯1
Напиши свой ответ в комментариях. Если ты знаешь правильный ответ, то мы будем рады видеть тебя на нашем контесте.
🔥5
Привет, друзья!

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

Понедельник (07.10.2024) Дайджест за предыдущую неделю

Вторник (08.10.2024) Знаете ли вы, как Namespace и cgroups обеспечивают изоляцию в контейнеризации?

Среда (09.10.2024)

Четверг (10.10.2024) Obsidian LiveSync - совместная работа над проектной документацией

Пятница (11.10.2024) Пятничный кинорелакс

Суббота (12.10.2024) Задача

Воскресенье (13.10.2024) Текстовый разбор задачи


Спасибо, что остаетесь с нами! Надеемся, что эти материалы будут вам полезны. Удачи в новой неделе!

С уважением,
Команда канала "Код на салфетке".

#дайджест #материалы #новости #код_на_салфетке
🔥5👍1
Напиши свой ответ в комментариях. Если ты знаешь правильный ответ, то мы будем рады видеть тебя на нашем контесте.
🔥4
Знаете ли вы, как использовать Namespace и cgroups для обеспечения изоляции при контейнеризации?

Namespace изолирует системные аспекты, создавая отдельные пространства для каждого контейнера. Например:
- PID namespace: изолирует процессы
- Network namespace: изолирует сетевые интерфейсы
- Mount namespace: изолирует точки монтирования файловых систем

Cgroups управляет распределением системных ресурсов между контейнерами и устанавливает лимиты использования:

docker run -d --name appname \
--cpus 0.5 \
--memory 256m \
--memory-swap 512m \
--cpu-shares 512 \
imagename


В этом примере запуск Docker контейнера происходит с ограничениями cgroups:
--cpus 0.5 ограничивает использование CPU до 50% одного ядра
--memory 256m ограничивает память до 256 МБ
--memory-swap 512m устанавливает лимит подкачки в 512 МБ
--cpu-shares 512 задает относительный вес CPU

Так, namespace обеспечивает изоляцию на уровне системных ресурсов, а cgroups предоставляет контроль над количеством ресурсов, доступных контейнеру.

Код на салфетке x Кусочки кода
🔥7
Напиши свой ответ в комментариях. Если ты знаешь правильный ответ, то мы будем рады видеть тебя на нашем контесте.
🔥5🤡1
Напиши свой ответ в комментариях. Если ты знаешь правильный ответ, то мы будем рады видеть тебя на нашем контесте.
🔥6
FastAPI 4. Модель пользователя и Alembic
Автор: Иван Ашихмин

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


Читать пост в Telegram

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

#Гайды #миграции #FastAPI #SQLAlchemy #подключение_БД #black #Классы_моделей #Alembic
🔥8👍1👏1🤝1
Приветствую, друзья!

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

Фильм: Константин: Повелитель тьмы

Год: 2005

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

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

Приятного просмотра!
🔥9👍1🤩1
Что выведет этот код? №42

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

Пример данных в таблице books:
- id: 1, title: "The Great Gatsby", rating: 4, description: "A classic novel about the 1920s."
- id: 2, title: "To Kill a Mockingbird", rating: 3, description: "A novel about racial injustice."
- id: 3, title: "1984", rating: 5, description: "A dystopian social science fiction."

Код ниже показывает, как это можно реализовать с помощью SQLAlchemy 2.

Что выведет этот код?
🔥5
Вчера мы опубликовали задачу, в которой нужно было обновить информацию о книге в базе данных, если её рейтинг ниже среднего по библиотеке и нового предложенного значения. Многие участники отметили, что задача оказалась не такой простой, как казалось на первый взгляд, из-за условий, которые могли легко быть упущены.

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

Пример данных в таблице:
- id: 1, title: "The Great Gatsby", rating: 4, description: "A classic novel about the 1920s."
- id: 2, title: "To Kill a Mockingbird", rating: 3, description: "A novel about racial injustice."
- id: 3, title: "1984", rating: 5, description: "A dystopian social science fiction."

Посмотрите на код ниже и определите, что произойдёт, если мы попытаемся обновить книгу "The Great Gatsby" с новым рейтингом 5 и новым описанием "A classic novel about the American dream.":

sync def update_book_info(
title: str, new_rating: int, new_description: str
) -> None:
async with session_maker() as session:
avg_rating_stmt = select(func.avg(Book.rating)).correlate_except(Book)
avg_rating = await session.execute(avg_rating_stmt)
avg_rating_value = avg_rating.scalar()

stmt = select(Book).where(Book.title == title)
result = await session.execute(stmt)
book = result.scalar_one_or_none()

if (
book
and book.rating < new_rating
and book.rating < avg_rating_value
):
stmt = (
update(Book)
.where(Book.id == book.id)
.values(rating=new_rating, description=new_description)
)
await session.execute(stmt)
await session.commit()


await update_book_info(
title="The Great Gatsby",
new_rating=5,
new_description="A classic novel about the American dream.",
)


Разбор кода:
1. Получение среднего рейтинга всех книг:
- Сначала вычисляется средний рейтинг всех книг в библиотеке с помощью запроса avg_rating_stmt = select(func.avg(Book.rating)).correlate_except(Book). Это значение будет использоваться для проверки, может ли рейтинг книги быть обновлён.
- В нашем примере средний рейтинг всех книг равен (4 + 3 + 5) / 3 = 4.

2. Поиск книги по названию:
- Следующим шагом программа ищет книгу с названием "The Great Gatsby". Если она найдена, то её данные загружаются для дальнейшей проверки.

3. Проверка условий:
- Программа проверяет три условия:
- Книга существует (она найдена в базе).
- Текущий рейтинг книги меньше нового рейтинга.
- Текущий рейтинг книги меньше среднего рейтинга по библиотеке.

В нашем случае, рейтинг книги "The Great Gatsby" равен 4. Новый рейтинг — 5. Средний рейтинг всех книг — 4.

4. Почему обновление не произойдёт:
- Хотя рейтинг книги меньше нового предложенного значения (4 < 5), он не меньше среднего рейтинга (4 = 4). Это значит, что одно из условий не выполнено, и обновления не будет.

Итог:
Книга "The Great Gatsby" не будет обновлена, так как её текущий рейтинг равен среднему рейтингу всех книг, что не позволяет пройти последнюю проверку.

Правильный ответ:
Ничего не произойдёт, так как не соответствует условиям.

Как это исправить:
Если вы хотите обновить книгу при равенстве рейтинга со средним, можно изменить условие проверки на book.rating <= avg_rating_value, чтобы включить случаи, когда рейтинг книги равен среднему.
🤯5🔥1
Привет, друзья!

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

Понедельник (14.10.2024) Дайджест за предыдущую неделю

Вторник (15.10.2024) Знаете ли вы, как использовать Namespace и cgroups для обеспечения изоляции при контейнеризации?

Среда (16.10.2024)

Четверг (17.10.2024) FastAPI 4. Модель пользователя и Alembic

Пятница (18.10.2024) Пятничный кинорелакс

Суббота (19.10.2024) Задача

Воскресенье (20.10.2024) Текстовый разбор задачи


Спасибо, что остаетесь с нами! Надеемся, что эти материалы будут вам полезны. Удачи в новой неделе!

С уважением,
Команда канала "Код на салфетке".

#дайджест #материалы #новости #код_на_салфетке
🔥8
Хотите узнать, как использовать multiprocessing в Python для обхода ограничений GIL?

В одном из прошлых постов мы говорили о том, как GIL ограничивает параллельное выполнение задач. Сегодня посмотрим на практический пример использования модуля multiprocessing.

import multiprocessing

def heavy_computation(n):
return sum(i * i for i in range(n))

if __name__ == '__main__':
numbers = [10**7 + i for i in range(4)]
with multiprocessing.Pool(4) as pool:
results = pool.map(heavy_computation, numbers)
print(results)


Здесь GIL не позволит выполнить heavy_computation в нескольких потоках, так как это CPU-нагруженная задача. Чтобы обойти это ограничение, мы использовали модуль multiprocessing:

- Создается пул из 4 процессов: Pool(4).
- Каждый процесс работает в своей копии интерпретатора, обходя GIL.
- Функция выполняется параллельно на разных ядрах.

Код на салфетке x Кусочки кода
🔥9👍2🤩2
Сравнение hashmap C/C++ с dict Python (часть 3)
Автор: Eugene Kaddo

Данная статья продолжит рассмотрение темы отличия hash table C/C++ от dict Python и способов их реализации.


Читать пост в Telegram

Файлы к посту, можно получить в боте по коду: 646514

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

#Python #Сравнение_Python_и_C #C #C++ #hash_map #hash_table #dict
🔥6🤩2
🐍 Телеграм-канал PythonProgggg 📢

Хотите глубже погрузиться в увлекательный мир программирования на Python? Не ищите дальше, чем телеграм-канал PythonProgggg! 🚀

Присоединяйтесь к нам на https://t.iss.one/PythonProgggg и приготовьтесь к ежедневной порции благ Python! 🎉

🔸 Почему стоит выбрать PythonProgggg?

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

Полезные ресурсы: будьте в курсе последних библиотек, фреймворков и инструментов Python. Мы поможем вам найти лучшие ресурсы для улучшения ваших навыков работы с Python.

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

Примеры кода: черпайте вдохновение из множества практических примеров кода, которые вы можете изучить и применить в своих собственных проектах.

Будьте в курсе: мы держим вас в курсе последних новостей и тенденций в мире Python, гарантируя, что вы никогда не пропустите важные обновления.

Не упустите возможность стать профессионалом Python! Присоединяйтесь к нам сегодня на https://t.iss.one/PythonProgggg. Вместе раскроем весь потенциал программирования на Python! 🐍💻
4🔥3🤡2👍1
Приветствую!

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

Фильм: Гипнотик

Год: 2024

У детектива Дэнни Рурка похищают 7-летнюю дочь. Преступник был пойман, но девочку найти так и не удалось. Пытаясь справиться с трагедией, опытный коп начинает посещать психотерапевта. Однажды Дэнни и его напарник получают ориентировку на возможное ограбление банка. Прибыв на место, Рурк обращает внимание на подозрительного мужчину, который при помощи кодовых слов начинает контролировать окружающих и пытается осуществить ограбление.

Приятного просмотра и до встречи на следующей неделе с новым кинопостом!
🔥4