Как автоматически генерировать сложные пароли для всей команды
Ваш пароль "qwerty123" прекрасен... если вы хотите подарить хакеру новый автомобиль. Давайте генерировать лучше!
Слабые пароли - главная дыра в безопасности. А придумывать и хранить десятки сложных паролей для разных сервисов не может даже человек с памятью как у Шерлока. Доверьте это машине.
Однострочник на Python в помощь всей команде:
Мы используем модуль
А как вы управляете паролями в своей команде?
🌐 @helcode | #python
Ваш пароль "qwerty123" прекрасен... если вы хотите подарить хакеру новый автомобиль. Давайте генерировать лучше!
Слабые пароли - главная дыра в безопасности. А придумывать и хранить десятки сложных паролей для разных сервисов не может даже человек с памятью как у Шерлока. Доверьте это машине.
Однострочник на Python в помощь всей команде:
import secrets
import string
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
password = ''.join(secrets.choice(alphabet) for i in range(16))
print(password) # Пример: 'xT5&!k8@qL9#vR2$'
Мы используем модуль
secrets, который криптографически безопасен (в отличие от random). string.ascii_letters + string.digits - это наш алфавит (буквы и цифры). Добавляем спецсимволы для сложности. Длина 16 символов - отличный старт.А как вы управляете паролями в своей команде?
🌐 @helcode | #python
👍2
Автоматизируйте свои чат-боты: хватит отвечать на одни и те же вопросы!
Ваша команда снова спрашивает, «каой пароль от тестовой БД?».
🤖Пора научить бота делать вашу работу за вас.
В любой команде есть рутинные вопросы, которые отвлекают от работы. «Где документация?», «Как запустить проект?», «Кто дежурный?». Вместо того чтобы в сотый раз копировать один и тот же ответ, можно написать простого бота для Telegram или Slack.
Вот пример на Python с библиотекой
Мы используем
Какой самый частый и раздражающий вопрос вы получаете в чате?
🌐 @helcode | #python
Ваша команда снова спрашивает, «каой пароль от тестовой БД?».
🤖Пора научить бота делать вашу работу за вас.
В любой команде есть рутинные вопросы, которые отвлекают от работы. «Где документация?», «Как запустить проект?», «Кто дежурный?». Вместо того чтобы в сотый раз копировать один и тот же ответ, можно написать простого бота для Telegram или Slack.
Вот пример на Python с библиотекой
python-telegram-bot для обработки частого вопроса.from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
# Бот отвечает на сообщение с ключевым словом
await update.message.reply_text(
"Коллега, привет! Вот частые ответы:\n"
"• Пароль от БД: 'supersecret'\n"
"• Документация: https://wiki.our-company.com/\n"
"• Как запустить: см. файл README.md в корне проекта"
)
if __name__ == '__main__':
app = Application.builder().token("YOUR_TOKEN").build()г
app.add_handler(MessageHandler(filters.TEXT & filters.Regex(r'(?i)(пароль|документация|как запустить)'), help_command))
app.run_polling()
Мы используем
MessageHandler с фильтром filters.Regex(). Он ловит любое текстовое сообщение, в котором есть слова «пароль», «документация» или «как запустить» (регистр неважен благодаря `(?i)`), и автоматически отвечает заготовленным текстом.Какой самый частый и раздражающий вопрос вы получаете в чате?
Это как поставить на частый вопрос автоответчик «я в отпуске», только Вы не в отпуске, а просто пьете кофе, пока бот работает.
🌐 @helcode | #python
👍2
Хватит хардкодить пароли в скриптах! Где и как хранить секреты
API-токены, пароли от БД, ключи шифрования. Они не должны лежать в открытом виде в коде, который вы заливаете на GitHub. Но как тогда скрипт получит к ним доступ? Решение есть.
Используем переменные окружения и файлы.
Способ 1: переменные окружения (просто и достаточно для многих случаев)
Задаем переменную в сессии или в файле
И используем в Python-скрипте:
Способ 2: Файлы с секретами (более безопасно)
Создаем файл, который не будет попадать в git:
Читаем его в коде с помощью библиотеки
Немного теории:
- Переменные окружения — это изолированное пространство памяти процесса. Их не видно в списке запущенных процессов (в отличие от аргументов командной строки).
-
Где вы храните свои секреты?
Признавайтесь, мы не осудим
🌐 @helcode | #bash #python
password = "12345" в коде — это как оставить ключи от квартиры в двери. API-токены, пароли от БД, ключи шифрования. Они не должны лежать в открытом виде в коде, который вы заливаете на GitHub. Но как тогда скрипт получит к ним доступ? Решение есть.
Используем переменные окружения и файлы.
Способ 1: переменные окружения (просто и достаточно для многих случаев)
Задаем переменную в сессии или в файле
~/.bashrc / ~/.zshrc:export DB_PASSWORD="my_super_secret_password_123"
И используем в Python-скрипте:
import os
db_pass = os.environ.get('DB_PASSWORD')
if not db_pass:
raise ValueError("Не задан пароль от БД!")
Способ 2: Файлы с секретами (более безопасно)
Создаем файл, который не будет попадать в git:
# .env file (добавляем в .gitignore!)
DB_HOST=localhost
DB_USER=admin
DB_PASSWORD=secret
Читаем его в коде с помощью библиотеки
python-dotenv:
pip install python-dotenv
from dotenv import load_dotenv
load_dotenv() # Загружает переменные из файла .env в os.environ
db_pass = os.getenv('DB_PASSWORD')
Немного теории:
- Переменные окружения — это изолированное пространство памяти процесса. Их не видно в списке запущенных процессов (в отличие от аргументов командной строки).
-
.env файлы — это удобный способ локальной разработки. На продакшене (сервере) эти же переменные задаются через конфигурацию systemd, Docker или панели управления хостингом.Где вы храните свои секреты?
Признавайтесь, мы не осудим
Хардкодить пароль в коде — это как написать пин-код от карты на ней же шариковой ручкой. Удобно, но недальновидно.
🌐 @helcode | #bash #python
👍3🤣1
Автоматическое создание алиасов для часто ошибающихся команд
Наша память избирательна, особенно в 3 часа ночи, когда деплой горит. Постоянно печатать
Просто добавьте эти строки в ваш
Алиасы — это пользовательские сокращения или замены для длинных команд. Shell просто подставляет нужную строку вместо короткого алиаса. Это самый простой способ сэкономить нервы и количество нажатий на клавиатуру.
Какой ваш самый частый ляп в консоли?
🌐 @helcode | #bash
git comit? git pusht? Пора остановить это безумие! Наша память избирательна, особенно в 3 часа ночи, когда деплой горит. Постоянно печатать
git stauts вместо git status - это не про вас, это про всех. Зачем мучиться, если можно научить shell подстраховываться?Просто добавьте эти строки в ваш
~/.bashrc или ~/.zshrc:# Исправляем опечатки в git
alias git='() { if [[ $1 == "comit" ]]; then shift; command git commit "$@"; elif [[ $1 == "pusht" ]]; then shift; command git push "$@"; else command git "$@"; fi; }'
# Или универсальный солдат для частых опечаток:
alias comit='git commit'
alias pusht='git push'
alias gs='git status' # для ленивых, пользуюсь
Алиасы — это пользовательские сокращения или замены для длинных команд. Shell просто подставляет нужную строку вместо короткого алиаса. Это самый простой способ сэкономить нервы и количество нажатий на клавиатуру.
Какой ваш самый частый ляп в консоли?
Это как завести личного ассистента, который поправляет вас, когда вы говорите «симпОтичный». Но только для терминала. И без обид.
🌐 @helcode | #bash
👍1
Как парсить PDF без специализированных библиотек
Парсить PDF на чистом Python — это как есть суп вилкой. Но иногда это бывает нужно...
Многие простые PDF можно "выстрелить" стандартными утилитами и регулярками.
PDF — это сложный формат, но часто текст внутри него хранится в открытом виде. Утилита
🌐 @helcode | #bash
Парсить PDF на чистом Python — это как есть суп вилкой. Но иногда это бывает нужно...
PyPDF2, pdfminer, tabula — все это круто, пока Вам нельзя ставить лишние зависимости в проект или пока вам нужен лишь клочок текста из простого PDF. Иногда задача настолько мала, что тащить за собой библиотеку — это overkill.Многие простые PDF можно "выстрелить" стандартными утилитами и регулярками.
# Используем pdftotext (из пакета poppler-utils)
pdftotext my_document.pdf - | grep -i "искомый текст"
# На Python, читаем PDF как бинарник и ищем строку
import re
with open('file.pdf', 'rb') as f:
pdf_content = f.read()
# Ищем что-то похожее на текст (опасно, но для простых случаев работает)
text_match = re.search(b'(Hello World)', pdf_content)
if text_match:
print(text_match.group(1).decode('utf-8'))
PDF — это сложный формат, но часто текст внутри него хранится в открытом виде. Утилита
pdftotext пытается его извлечь, а дальше мы можем работать с текстом как обычно. Внимание: это хак, а не решение для сложных PDF с таблицами и картинками!Предупреждаю, этот метод такой же надежный, как построить мост из спагетти. Но для быстрого прототипа или личных задач — вполне пригоден!
🌐 @helcode | #bash
👍2🤔2
Ваши скрипты умеют принимать правильные решения? (Просто о условных операторах)
Любой скрипт, который делает что-то полезное, рано или поздно должен уметь выбирать. «Если сервер не ответил, попробовать еще раз», «Если файл большой, сжать его перед отправкой». Без условий код — просто линейный набор команд, как рецепт для робота.
Смотрите, как оживает ваш код с условиями.
Было (скрипт-зомби):
Стало (скрипт-интеллектуал):
Код возврата любой команды (
А вы проверяете успешность команд в своих скриптах?
🌐 @helcode | #bash
if, else, elif... Это не заклинание, это ваши спиннеры для кода! 🧙♂️Любой скрипт, который делает что-то полезное, рано или поздно должен уметь выбирать. «Если сервер не ответил, попробовать еще раз», «Если файл большой, сжать его перед отправкой». Без условий код — просто линейный набор команд, как рецепт для робота.
Смотрите, как оживает ваш код с условиями.
Было (скрипт-зомби):
#!/bin/bash
echo "Начинаем деплой..."
curl http://my-server.com/deploy
echo "Готово." # Всегда "Готово", даже если сервер сгорел
Стало (скрипт-интеллектуал):
#!/bin/bash
echo "Начинаем деплой..."
if curl -f http://my-server.com/deploy; then
echo "✅ Деплой успешен!"
else
echo "❌ Ошибка деплоя! Сервер не ответил."
exit 1
fi
Код возврата любой команды (
0 — успех, не 0 — ошибка) — это ключ к принятию решений. Конструкция if [ условие ]; then... проверяет этот код. Флаг -f у curl как раз заставляет его возвращать ненулевой код при HTTP-ошибке (404, 500 и т.д.).А вы проверяете успешность команд в своих скриптах?
Писать скрипты без условий — это как играть в шахматы, всегда ходя только пешкой на одну клетку. Можно, но зачем?
🌐 @helcode | #bash
👍4
Тайминги и блокировки: как избежать «снежного кома» в cron
🤔 Представьте: задача в
Это классическая проблема наложения задач.
Решения:
1.
2.
Ключ
🌐 @helcode | #linux #cron #automation #performance
🤔 Представьте: задача в
cron -е запускается каждые 5 минут, но иногда выполняется 10. Что будет? Через час у вас будет 12 параллельных процессов, грузящих систему!Это классическая проблема наложения задач.
Решения:
1.
timeout: жестко ограничить время выполнения. * * * * * timeout 300 /path/to/script.sh # Остановить через 5 минут2.
flock: поставить блокировку на файл, чтобы скрипт не запускался, если предыдущий экземпляр еще работает. * * * * * /usr/bin/flock -n /tmp/myscript.lock /path/to/script.shКлюч
-n означает «не ждать». Если скрипт уже работает — новый запуск просто проигнорируется. Идеально для защиты от дублирования!🌐 @helcode | #linux #cron #automation #performance
❤3👎1🤔1
requirements.txt звонит из 2010-го и просит вернуть его. Чем заменить?
Все мы знаем и... немного ненавидим этот файл.
Встречаем
👀 Вот как это выглядит:
*
*
*
Но это еще не всё! Для полного счастья используйте
А что используете вы для управления зависимостями? 🗳
1. Старая гвардия
2.
3.
4. Anaconda (для data science)
5. Свой метод? Делитесь в комментах!
🌐 @helcode | #toml
Все мы знаем и... немного ненавидим этот файл.
requests==2.28.1, pandas~=1.5.0, aiohttp. А потом — «ой, а почему у меня не запускается?». Ручное управление версиями, хаос в зависимостях, вечные конфликты. Это как собирать мебель без инструкции, надеясь, что все винтики подойдут.Встречаем
pyproject.toml — новый стандарт, который заменил всё. Это единый файл конфигурации для сборки, зависимостей и метаданных вашего проекта. Больше никаких setup.py, requirements.txt, setup.cfg и MANIFEST.in!👀 Вот как это выглядит:
# pyproject.toml
[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my_awesome_tool"
version = "0.1.0"
dependencies = [
"requests>=2.28.1",
"pandas~=1.5.0", # Совместимость с версиями 1.5.0+
"aiohttp"
]
[project.optional-dependencies]
dev = ["pytest", "black", "flake8"] # Зависимости для разработки!
*
[build-system]: Говорит pip, как собирать ваш пакет.*
[project]: Основные метаданные и обязательные зависимости.*
[project.optional-dependencies]: Группы зависимостей (например, для тестов, линтинга, docs). Установить их можно так: pip install .[dev]Но это еще не всё! Для полного счастья используйте
poetry или pdm — они не только управляют зависимостями, но и создают виртуальное окружение и блокируют версии в poetry.lock/pdm.lock, гарантируя идентичные окружения у всех разработчиков. Это уровень «профи».А что используете вы для управления зависимостями? 🗳
1. Старая гвардия
requirements.txt (работает и ладно!)2.
pyproject.toml + pip (современно и по стандарту)3.
poetry / pdm (магия и комфорт)4. Anaconda (для data science)
5. Свой метод? Делитесь в комментах!
P.S. Если ваш requirements.txt сейчас плачет в углу — не говорите, что это мы вас надоумили. Просто дайте ему почитать pyproject.toml, пусть постыдится.
🌐 @helcode | #toml
multiprocessing или threading? Вопрос на миллион потоков... и процессов!
Ваш скрипт тормозит и вы хотите распараллелить все на свете.
🤔 Но что выбрать? Потоки? Процессы?
Ответ кроется в трех буквах — GIL (Global Interpreter Lock).
☕️ Это такой злой бариста в кофейне Python, который не дает нескольким потокам одновременно молоть зёрна (выполнять Python-код). Но у каждого процесса своя кофейня (и свой GIL)!
Код-пример (CPU-bound):
Код-пример (I/O-bound):
Выбор зависит от типа задачи. Не используйте потоки для вычислений — вы не получите прироста, а только накладные расходы. Не используйте процессы для простых HTTP-запросов — вы создадите слишком много тяжелых процессов.
А вы чаще сталкиваетесь с I/O или CPU-bound задачами? И какой ваш любимый способ паралеллить?
🌐 @helcode | #python
Ваш скрипт тормозит и вы хотите распараллелить все на свете.
🤔 Но что выбрать? Потоки? Процессы?
Ответ кроется в трех буквах — GIL (Global Interpreter Lock).
☕️ Это такой злой бариста в кофейне Python, который не дает нескольким потокам одновременно молоть зёрна (выполнять Python-код). Но у каждого процесса своя кофейня (и свой GIL)!
Код-пример (CPU-bound):
# Много вычислений -> multiprocessing
import multiprocessing
import math
def calculate_factorial(n):
return math.factorial(n)
if __name__ == '__main__':
numbers = [100000, 200000, 300000] * 5 # Тяжелая работа
with multiprocessing.Pool() as pool:
results = pool.map(calculate_factorial, numbers) # 🚀 Запуск на всех ядрах!
Код-пример (I/O-bound):
# Много ожидания -> threading
import threading
import requests
def check_site(url):
response = requests.get(url)
return response.status_code
urls = ['https://google.com', 'https://yandex.ru', ...] * 10
threads = []
for url in urls:
thread = threading.Thread(target=check_site, args=(url,))
thread.start()
threads.append(thread)
for thread in threads:
thread.join() # 🧵 Ждем все потоки
Выбор зависит от типа задачи. Не используйте потоки для вычислений — вы не получите прироста, а только накладные расходы. Не используйте процессы для простых HTTP-запросов — вы создадите слишком много тяжелых процессов.
А вы чаще сталкиваетесь с I/O или CPU-bound задачами? И какой ваш любимый способ паралеллить?
P.S. GIL — это не баг, это фича, которая не дает твоему коду сломать интерпретатор. Но иногда так хочется его пристрелить... (шучу, не шучу).
🌐 @helcode | #python
Ваши логи выглядят как поток сознания писателя-авангардиста? Пора навести порядок!
📖 Читать обычные текстовые логи, где вперемешку идут отладочные сообщения, ошибки и информационные записи, - это как искать иголку в стоге сена. А если нужно автоматически анализировать логи? На помощь приходят структурированные логи в формате JSON.
Используем встроенный модуль
Настройка структурированного логирования:
Вместо неструктурированной строки мы получаем JSON-объект:
✅ Преимущества:
- Легко парсить автоматизированными системами (ELK Stack, Loki, CloudWatch).
- Можно добавлять любые метаданные к каждому событию (
- Упрощен поиск и фильтрация по конкретным полям.
Как вы справляетесь с анализом логов?
🌐 @helcode | #python
📖 Читать обычные текстовые логи, где вперемешку идут отладочные сообщения, ошибки и информационные записи, - это как искать иголку в стоге сена. А если нужно автоматически анализировать логи? На помощь приходят структурированные логи в формате JSON.
Используем встроенный модуль
logging в Python, но с кастомным форматтером.Настройка структурированного логирования:
import logging
import json
from datetime import datetime
class StructuredMessage:
def __init__(self, message, **kwargs):
self.message = message
self.kwargs = kwargs
def __str__(self):
# Создаем словарь с основным сообщением и дополнительными полями
log_data = {
'timestamp': datetime.utcnow().isoformat() + 'Z',
'level': logging.getLevelName(logging.getLogger().getEffectiveLevel()),
'message': self.message,
**self.kwargs # Добавляем все переданные ключевые аргументы
}
return json.dumps(log_data)
# Настраиваем логирование
logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
# Не нужно форматировать, тк наши сообщения уже строки JSON
handler.setFormatter(logging.Formatter('%(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
# Использование
logger.info(StructuredMessage("User logged in", user_id=123, ip="192.168.1.1", success=True))
logger.error(StructuredMessage("DB connection failed", attempt=3, timeout=30))
Вместо неструктурированной строки мы получаем JSON-объект:
{"timestamp": "2023-10-26T10:30:15.123456Z", "level": "INFO", "message": "User logged in", "user_id": 123, "ip": "192.168.1.1", "success": true}✅ Преимущества:
- Легко парсить автоматизированными системами (ELK Stack, Loki, CloudWatch).
- Можно добавлять любые метаданные к каждому событию (
user_id, request_id, execution_time).- Упрощен поиск и фильтрация по конкретным полям.
Как вы справляетесь с анализом логов?
Переход на структурированные логи - это как перейти от расшифровки древних свитков к аккуратной Excel-таблице. Информация та же, а работать в разы удобнее.
🌐 @helcode | #python
👍3
Как заставить скрипты общаться друг с другом: не только HTTP
Ваши скрипты живут в вакууме и не общаются? Пора познакомить их друг с другом! 🤝
Часто одна автоматизированная задача должна запускать другую или передавать ей данные. Делать это через запись в файл и постоянный опрос - неэлегантно. Есть более эффективные способы межпроцессного взаимодействия (IPC).
👀 Рассмотрим несколько способов, кроме очевидного HTTP.
Способ 1: очереди сообщений (Message Queues) на примере Redis
Способ 2: Named Pipes (именованные каналы) в Linux/macOS
* Очереди сообщений идеальны для построения распределенных систем. Гарантируют доставку, позволяют балансировать нагрузку между несколькими "воркерами".
* Именованные каналы - очень простой способ одноразовой передачи данных между процессами на одной машине. Работает на уровне файловой системы.
Как ваши скрипты общаются между собой?
🌐 @helcode | #python #bash
Ваши скрипты живут в вакууме и не общаются? Пора познакомить их друг с другом! 🤝
Часто одна автоматизированная задача должна запускать другую или передавать ей данные. Делать это через запись в файл и постоянный опрос - неэлегантно. Есть более эффективные способы межпроцессного взаимодействия (IPC).
👀 Рассмотрим несколько способов, кроме очевидного HTTP.
Способ 1: очереди сообщений (Message Queues) на примере Redis
# Скрипт-отправитель (producer.py)
import redis
import json
r = redis.Redis(host='localhost', port=6379, db=0)
task = {'user_id': 456, 'action': 'generate_report'}
r.lpush('task_queue', json.dumps(task)) # Кладем задачу в очередь
# Скрипт-получатель (consumer.py)
import redis
import json
import time
r = redis.Redis(host='localhost', port=6379, db=0)
while True:
# Блокирующее ожидание задачи из очереди (ждем 30 сек)
_, task_json = r.brpop('task_queue', timeout=30)
if task_json:
task = json.loads(task_json)
print(f"Обрабатываю задачу: {task}")
# ... обработка ...
time.sleep(1)
Способ 2: Named Pipes (именованные каналы) в Linux/macOS
# Создаем канал
mkfifo my_pipe
# Скрипт-читатель (зависнет, пока не появятся данные)
cat my_pipe
# Скрипт-писатель
echo "Hello from another script!" > my_pipe
* Очереди сообщений идеальны для построения распределенных систем. Гарантируют доставку, позволяют балансировать нагрузку между несколькими "воркерами".
* Именованные каналы - очень простой способ одноразовой передачи данных между процессами на одной машине. Работает на уровне файловой системы.
Как ваши скрипты общаются между собой?
Научить скрипты общаться - это как организовать работу отдела: можно кидать записки через стол (файлы), а можно настроить слаженный процесс с задачами и очередями. Второе - эффективнее.
🌐 @helcode | #python #bash
👍4
Тайм-ауты и повторные попытки: делаем ваши скрипты устойчивыми к сбоям
Ваш скрипт падает от малейшей ошибки сети? Пора научить его быть настойчивее!
В реальном мире сеть ненадежна, сервисы падают, а ответы задерживаются. Наивный скрипт, который не учитывает этого, обречен на частые failures. Устойчивость (resilience) - ключевое свойство для продакшн-автоматизации.
Паттерн "Retry with backoff" (Повтор с экспоненциальной задержкой).
Реализация на Python с помощью библиотеки
➤
➤
➤
С какими сбоями чаще всего сталкиваются ваши скрипты?
🌐 @helcode | #python
Ваш скрипт падает от малейшей ошибки сети? Пора научить его быть настойчивее!
В реальном мире сеть ненадежна, сервисы падают, а ответы задерживаются. Наивный скрипт, который не учитывает этого, обречен на частые failures. Устойчивость (resilience) - ключевое свойство для продакшн-автоматизации.
Паттерн "Retry with backoff" (Повтор с экспоненциальной задержкой).
Реализация на Python с помощью библиотеки
tenacity:from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import requests
@retry(
stop=stop_after_attempt(5), # Остановиться после 5 попыток
wait=wait_exponential(multiplier=1, min=2, max=30), # Экспоненциальная задержка: 2s, 4s, 8s... макс. 30s
retry=retry_if_exception_type(requests.exceptions.RequestException) # Повторять только при ошибках сети
)
def call_unreliable_api(url):
response = requests.get(url, timeout=3)
response.raise_for_status() # Выбросит исключение при HTTP-ошибке
return response.json()
# Использование
try:
data = call_unreliable_api("https://api.example.com/shaky-endpoint")
print("Успех!", data)
except Exception as e:
print(f"Не удалось после всех попыток: {e}")
➤
wait_exponential: увеличивает задержку между попытками по экспоненте. Это вежливо по отношению к упавшему серверу (не DDoSим его) и дает ему время на восстановление.➤
stop_after_attempt: защита от бесконечных петель. Всегда должен быть лимит.➤
retry_if_exception_type: важно повторять только те ошибки, которые имеют смысл retry'ить (проблемы сети, тайм-ауты, 5xx ошибки сервера). Ошибку 404 (Not Found) retry'ить бессмысленно.С какими сбоями чаще всего сталкиваются ваши скрипты?
Добавление retry-логики - это как дать скрипту несколько дополнительных жизней в видеоигре. Он может проиграть первый раунд, но в итоге все равно победит. 🎮
🌐 @helcode | #python
🤔2
Как избежать race condition: локи для идущих в ногу скриптов
🚪 Два скрипта заходят в одну папку... Звучит как начало плохой IT-шутки и большой проблемы!
Если один и тот же критический ресурс (файл, запись в БД, внешний API) могут одновременно использовать несколько экземпляров вашего скрипта - возникает состояние гонки (race condition). Результат может быть непредсказуемым: поврежденные данные, двойное списание средств, бессмысленная нагрузка.
Используем файловые блокировки (file locks). В Python для этого есть удобная библиотека
Пример: гарантируем, что только один экземпляр скрипта будет выполнять критическую операцию
➤ FileLock создает одноименный lock-файл. Попытка захватить lock, который уже у кого-то есть, будет блокировать выполнение (
➤ Менеджер контекста (
➤ Это работает и между разными скриптами на разных языках, если они соблюдают одинаковый protocol (проверяют наличие одного и того же lock-файла).
В ваших скриптах есть критические секции? Как вы их защищаете?
🌐 @helcode | #python
🚪 Два скрипта заходят в одну папку... Звучит как начало плохой IT-шутки и большой проблемы!
Если один и тот же критический ресурс (файл, запись в БД, внешний API) могут одновременно использовать несколько экземпляров вашего скрипта - возникает состояние гонки (race condition). Результат может быть непредсказуемым: поврежденные данные, двойное списание средств, бессмысленная нагрузка.
Используем файловые блокировки (file locks). В Python для этого есть удобная библиотека
filelock.Пример: гарантируем, что только один экземпляр скрипта будет выполнять критическую операцию
from filelock import FileLock
import time
# Создаем lock-файл. Его наличие будет сигналом, что ресурс занят.
lock_path = "/tmp/my_script.lock"
# Используем менеджер контекста для гарантированного освобождения блокировки
with FileLock(lock_path, timeout=10): # Ждем 10 секунд, если lock занят
print("🔒 Lock acquired! Начинаю критическую операцию...")
# Здесь работа с общим ресурсом
time.sleep(5) # Имитация долгой работы
print("✅ Операция завершена. Lock released.")
# После выхода из блока 'with' блокировка автоматически снимается
➤ FileLock создает одноименный lock-файл. Попытка захватить lock, который уже у кого-то есть, будет блокировать выполнение (
timeout) или вызовет исключение.➤ Менеджер контекста (
with) гарантирует, что блокировка будет снята даже если внутри блока произойдет ошибка.➤ Это работает и между разными скриптами на разных языках, если они соблюдают одинаковый protocol (проверяют наличие одного и того же lock-файла).
В ваших скриптах есть критические секции? Как вы их защищаете?
Использование lock-файлов - это как повесить табличку «не беспокоить» на дверь офиса. Вежливо и предотвращает неловкие ситуации.
🌐 @helcode | #python
👍2❤1
Парсим сайты, которые не хотят, чтобы их парсили: обход блокировок
Современные сайты защищаются от парсинга: капчи, блокировка по IP, анализ поведения браузера. Наивный
Используем Selenium WebDriver с Stealth-плагином и ротируем User-Agent.
Настройка "стелс"-браузера на Python:
➤ Ротация User-Agent: смена «отпечатка» браузера делает запросы менее похожими друг на друга.
➤ Selenium Stealth: плагин скрывает следы автоматизации, которые ищут анти-бот системы (например, наличие
➤ HEADLESS-режим: запуск без GUI, но его одного часто недостаточно.
Важно: всегда проверяйте
Приходилось ли вам бороться с анти-бот системами?
🌐 @helcode | #python
Современные сайты защищаются от парсинга: капчи, блокировка по IP, анализ поведения браузера. Наивный
requests.get() уже не работает. Нужно маскироваться под человека.Используем Selenium WebDriver с Stealth-плагином и ротируем User-Agent.
Настройка "стелс"-браузера на Python:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium_stealth import stealth
import random
# Создаем опции Chrome
options = Options()
options.add_argument("--headless=new") # Запуск в фоне
options.add_argument(f"--user-agent={random.choice(user_agents)}") # Рандомный UA
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options)
# Применяем stealth-плагин для сокрытия автоматизации
stealth(driver,
languages=["en-US", "en"],
vendor="Google Inc.",
platform="Win32",
webgl_vendor="Intel Inc.",
renderer="Intel Iris OpenGL Engine",
fix_hairline=True,
)
driver.get("https://hard-to-parse-site.com")
# Дальше работаем как с обычным браузером
➤ Ротация User-Agent: смена «отпечатка» браузера делает запросы менее похожими друг на друга.
➤ Selenium Stealth: плагин скрывает следы автоматизации, которые ищут анти-бот системы (например, наличие
navigator.webdriver).➤ HEADLESS-режим: запуск без GUI, но его одного часто недостаточно.
Важно: всегда проверяйте
robots.txt и Terms of Service сайта. Уважайте нагрузку на чужой сервер (добавляйте задержки time.sleep()).Приходилось ли вам бороться с анти-бот системами?
Писать парсер для защищенного сайта — это игра в кошки-мышки с системными администраторами этого сайта. Главное — не переходить в DDoS. 🐭🐱
🌐 @helcode | #python
Скрипты-самоубийцы: как автоматически остановить скрипт, если он сломался
Ваш скрипт завис и висит сутками, съедая ресурсы? Научите его вовремя уходить с достоинством!
Скрипты, которые работают с внешними ресурсами (сеть, БД, API), могут внезапно зависнуть на неопределенное время. Это съедает память, блокирует другие процессы и портит картину мониторинга. Нужен встроенный механизм самоликвидации.
Используем декораторы и сигналы для установки таймаутов.
Способ 1: таймаут на отдельную функцию (декоратор)
➤ Сигнал SIGALRM: посылается ядром Linux по истечении времени, заданного
➤ Декоратор
➤ Важно: этот метод работает только в главном потоке и не для всех операций (например, некоторые системные вызовы могут быть не прерваны).
Сталкивались ли вы с зависанием скриптов?
🌐 @helcode | #python
Ваш скрипт завис и висит сутками, съедая ресурсы? Научите его вовремя уходить с достоинством!
Скрипты, которые работают с внешними ресурсами (сеть, БД, API), могут внезапно зависнуть на неопределенное время. Это съедает память, блокирует другие процессы и портит картину мониторинга. Нужен встроенный механизм самоликвидации.
Используем декораторы и сигналы для установки таймаутов.
Способ 1: таймаут на отдельную функцию (декоратор)
import signal
from functools import wraps
class TimeoutException(Exception):
pass
def timeout(seconds=10):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# Устанавливаем обработчик сигнала ALARM
def handle_timeout(signum, frame):
raise TimeoutException("Функция выполнена дольше {seconds} секунд!")
old_handler = signal.signal(signal.SIGALRM, handle_timeout)
signal.alarm(seconds) # Заводим будильник
try:
result = func(*args, **kwargs)
finally:
signal.alarm(0) # Отключаем будильник
signal.signal(signal.SIGALRM, old_handler) # Восстанавливаем старый обработчик
return result
return wrapper
return decorator
# Использование
@timeout(5) # Максимум 5 секунд на выполнение
def call_slow_api():
import time
time.sleep(10) # Имитация долгого запроса
return "success"
try:
call_slow_api()
except TimeoutException:
print("Функция прервана по таймауту!")
➤ Сигнал SIGALRM: посылается ядром Linux по истечении времени, заданного
signal.alarm().➤ Декоратор
@timeout: позволяет обернуть любую функцию, установив для нее лимит выполнения.➤ Важно: этот метод работает только в главном потоке и не для всех операций (например, некоторые системные вызовы могут быть не прерваны).
Сталкивались ли вы с зависанием скриптов?
Научить скрипт самоликвидироваться — это как дать секретному агенту капсулу с ядом. Жестко, но эффективно для миссии.
🌐 @helcode | #python
👍2🤔1
Кэширование для ленивых: ускоряем скрипты в 100 раз без усилий
Ваш скрипт 100 раз ходит за одними и теми же данными? Пора дать ему память!
🏋️ Многие скрипты делают одни и те же «тяжелые» операции при каждом запуске: чтение больших файлов конфигурации, запросы к медленным API, сложные вычисления. Кэширование результатов между запусками — простой способ ускорить их в разы.
Используем декоратор
Кэширование результатов тяжелой функции:
➤
➤ При повторном вызове с теми же аргументами функция не выполняется, а результат возвращается из памяти.
➤ Важно: aункция должна быть чистой (pure) - возвращать одинаковый результат для одинаковых аргументов без side effects.
Где вы используете кэширование?
🌐 @helcode | #python
Ваш скрипт 100 раз ходит за одними и теми же данными? Пора дать ему память!
🏋️ Многие скрипты делают одни и те же «тяжелые» операции при каждом запуске: чтение больших файлов конфигурации, запросы к медленным API, сложные вычисления. Кэширование результатов между запусками — простой способ ускорить их в разы.
Используем декоратор
@cache из стандартной библиотеки Python (появился в 3.9+).Кэширование результатов тяжелой функции:
from functools import cache
import time
@cache # Волшебная строка, которая все кэширует
def get_weather(city):
# Имитация медленного HTTP-запроса к API погоды
time.sleep(2)
# Здесь реальный запрос: requests.get(f"http://weather.com/{city}").json()
return f"Погода в {city}: +25°C" # Возвращаем заглушку
# Первый вызов — медленный (2 секунды)
print(get_weather("Москва"))
# Все последующие вызовы с ТЕМ ЖЕ аргументом — мгновенные!
print(get_weather("Москва")) # Результат взят из кэша
print(get_weather("Москва")) # Снова из кэша
# Вызов с новым аргументом — снова медленный (2 секунды)
print(get_weather("Санкт-Петербург"))
# Кэш хранится ТОЛЬКО в течение работы программы.
# Для кэша между запусками нужны другие решения (redis, diskcache)
➤
@cache (или @lru_cache из functools для более старых версий) запоминает аргументы, с которыми вызывалась функция, и ее возвращаемое значение.➤ При повторном вызове с теми же аргументами функция не выполняется, а результат возвращается из памяти.
➤ Важно: aункция должна быть чистой (pure) - возвращать одинаковый результат для одинаковых аргументов без side effects.
Где вы используете кэширование?
Добавить @cache - это как поставить термос с кофе рядом с кроватью. Проснулся, выпил, уже бодрый - не надо идти на кухню и варить заново.
🌐 @helcode | #python
👍2🤔1
Мы переехали, обновились и снова в строю!
Бот @ScriptGeniusBot полностью функционирует в новой группе. Все скрипты на месте, поиск работает, категории доступны.
Что можно делать:
✅ Искать нужные скрипты
✅ Скачивать код одним файлом
Спасибо за терпение! Теперь работаем в усиленном режиме 💪
🌐 @helcode | #обновление #автоматизация
Бот @ScriptGeniusBot полностью функционирует в новой группе. Все скрипты на месте, поиск работает, категории доступны.
Что можно делать:
✅ Искать нужные скрипты
✅ Скачивать код одним файлом
Спасибо за терпение! Теперь работаем в усиленном режиме 💪
🌐 @helcode | #обновление #автоматизация
👍4
Как избежать хаоса: конфигурация скриптов в YAML
Ваши скрипты обрастают десятками параметров в коде? Пора вынести их в конфиг!
«Жесткие» параметры внутри кода (пути, адреса, пороги срабатывания) - это зло. При каждом изменении нужно лезть в код, рискуя что-то сломать. Правильное решение - выносить конфигурацию в отдельные файлы.
Используем YAML - человекочитаемый формат для конфигов.
Пример файла
Загрузка конфига в Python:
➤ YAML поддерживает сложные структуры (словари, списки), комментарии и более читаем, чем JSON.
➤ Отделение кода от конфигурации - ключевая практика DevOps. Это позволяет использовать один и тот же код в разных окружениях (dev, prod) без изменений.
➤ Версионирование: rонфиг-файлы можно хранить в git отдельно от кода с разными ветками для разных сред.
Как вы храните конфигурацию?
🌐 @helcode | #yaml #python
Ваши скрипты обрастают десятками параметров в коде? Пора вынести их в конфиг!
«Жесткие» параметры внутри кода (пути, адреса, пороги срабатывания) - это зло. При каждом изменении нужно лезть в код, рискуя что-то сломать. Правильное решение - выносить конфигурацию в отдельные файлы.
Используем YAML - человекочитаемый формат для конфигов.
Пример файла
config.yaml:database:
host: "localhost"
port: 5432
name: "my_app"
user: "admin"
logging:
level: "INFO"
file: "/var/log/my_app.log"
api:
endpoint: "https://api.example.com/v1"
timeout_seconds: 30
retry_attempts: 3
features:
enable_telemetry: false
cache_size: 1000
Загрузка конфига в Python:
import yaml # pip install PyYAML
with open("config.yaml", "r") as f:
config = yaml.safe_load(f)
# Теперь доступ к параметрам прост и безопасен
db_host = config['database']['host']
timeout = config['api']['timeout_seconds']
➤ YAML поддерживает сложные структуры (словари, списки), комментарии и более читаем, чем JSON.
➤ Отделение кода от конфигурации - ключевая практика DevOps. Это позволяет использовать один и тот же код в разных окружениях (dev, prod) без изменений.
➤ Версионирование: rонфиг-файлы можно хранить в git отдельно от кода с разными ветками для разных сред.
Как вы храните конфигурацию?
Переход на YAML-конфиги - это как перейти от управления государством через указы, написанные на салфетке, к полноценной конституции. Порядок и предсказуемость!
🌐 @helcode | #yaml #python
👍2
Автоматическое тестирование скриптов: оно вам нужно?
Вы запускаете скрипт и молитесь, чтобы он не сломал прод? Пора подружиться с тестами!
Скрипты для автоматизации - такое же ПО, как и веб-сервисы. Они могут содержать баги, которые приводят к потере данных или простою систем. Писать тесты для скриптов кажется overkill, но это окупается их надежностью.
🛠 Пишем простой unit-тест для функции из скрипта с помощью
Допустим, у нас есть функция в
Пишем тест в файле
Запуск тестов:
➤ Unit-тесты проверяют отдельные функции («юниты») изолированно от остального кода.
➤
➤ Тесты помогают без страха рефакторить код и добавлять новую функциональность, не ломая старое.
Вы пишете тесты для своих скриптов автоматизации?
🌐 @helcode | #python
Вы запускаете скрипт и молитесь, чтобы он не сломал прод? Пора подружиться с тестами!
Скрипты для автоматизации - такое же ПО, как и веб-сервисы. Они могут содержать баги, которые приводят к потере данных или простою систем. Писать тесты для скриптов кажется overkill, но это окупается их надежностью.
🛠 Пишем простой unit-тест для функции из скрипта с помощью
pytest.Допустим, у нас есть функция в
script.py:# script.py
def process_data(input_data):
"""Удаляет все числа меньше 10 из списка."""
if not isinstance(input_data, list):
raise ValueError("Input must be a list!")
return [x for x in input_data if x >= 10]
Пишем тест в файле
test_script.py:# test_script.py
import pytest
from script import process_data
# Стандартный тест на корректные данные
def test_process_data_positive():
assert process_data([1, 10, 20, 5]) == [10, 20]
# Тест на пограничное условие
def test_process_data_boundary():
assert process_data([9, 10]) == [10]
# Тест на некорректный ввод
def test_process_data_negative():
with pytest.raises(ValueError):
process_data("not a list")
Запуск тестов:
pytest -v test_script.py
➤ Unit-тесты проверяют отдельные функции («юниты») изолированно от остального кода.
➤
pytest - стандарт де-факто для тестирования в Python: простой синтаксис, информативные сообщения об ошибках.➤ Тесты помогают без страха рефакторить код и добавлять новую функциональность, не ломая старое.
Вы пишете тесты для своих скриптов автоматизации?
Писать тесты для скриптов — это как надевать страховку при работе на высоте. Кажется, что и так можно, но однажды это спасет вам проект.
🌐 @helcode | #python
👍2