- Home »

Как форматировать текст в Python 3
Форматирование текста в Python 3 — это то, с чем приходится сталкиваться каждый день при написании скриптов, автоматизации серверных задач и создании инструментов мониторинга. Возможно, вы думаете, что это банальная тема, но на самом деле правильное форматирование строк может превратить кривой скрипт в элегантный инструмент для работы с логами, конфигурационными файлами и API-ответами. В этой статье разберём все современные способы форматирования текста в Python 3, от базовых до продвинутых техник, которые реально пригодятся в серверной разработке.
Как это работает: основы форматирования строк
В Python 3 есть несколько способов форматирования строк, каждый со своими особенностями и областями применения. Давайте разберём их по порядку:
1. Старый добрый % форматирование
Этот метод пришёл из Python 2, но всё ещё активно используется в legacy-коде:
name = "nginx"
version = 1.18
uptime = 86400
message = "Server %s version %.2f has been running for %d seconds" % (name, version, uptime)
print(message)
# Вывод: Server nginx version 1.18 has been running for 86400 seconds
2. str.format() — более гибкий подход
Появился в Python 2.6 и стал стандартом для Python 3:
server_info = {
'name': 'web-server-01',
'cpu': 85.5,
'memory': 75.2,
'disk': 45.8
}
report = "Server {name}: CPU {cpu}%, Memory {memory}%, Disk {disk}%".format(**server_info)
print(report)
# Вывод: Server web-server-01: CPU 85.5%, Memory 75.2%, Disk 45.8%
3. f-strings (PEP 498) — современный стандарт
Доступны с Python 3.6+ и являются самым быстрым и читаемым способом:
hostname = "production-db"
connections = 150
max_connections = 200
status = f"Host {hostname}: {connections}/{max_connections} connections ({connections/max_connections*100:.1f}%)"
print(status)
# Вывод: Host production-db: 150/200 connections (75.0%)
Пошаговая настройка и практическое применение
Теперь рассмотрим реальные сценарии использования форматирования в серверных скриптах:
Шаг 1: Создание логгера с красивым форматированием
import datetime
import logging
def setup_custom_logger():
logger = logging.getLogger('server_monitor')
handler = logging.StreamHandler()
# Используем f-string для динамического форматирования
formatter = logging.Formatter(
fmt='%(asctime)s | %(levelname)s | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
return logger
logger = setup_custom_logger()
# Пример использования в мониторинге
def log_server_metrics(server_name, cpu, memory, disk):
timestamp = datetime.datetime.now()
# f-string с условным форматированием
cpu_status = "🔴 HIGH" if cpu > 80 else "🟢 OK"
memory_status = "🔴 HIGH" if memory > 90 else "🟢 OK"
message = f"[{server_name}] CPU: {cpu}% ({cpu_status}) | Memory: {memory}% ({memory_status}) | Disk: {disk}%"
logger.info(message)
# Использование
log_server_metrics("web-01", 85.5, 67.2, 45.8)
Шаг 2: Генерация конфигурационных файлов
def generate_nginx_config(server_name, port, upstream_servers):
config_template = """
server {{
listen {port};
server_name {server_name};
location / {{
proxy_pass http://{upstream_name};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}}
}}
upstream {upstream_name} {{
{upstream_config}
}}
"""
upstream_name = f"{server_name}_upstream"
upstream_config = "\n".join([f" server {server};" for server in upstream_servers])
return config_template.format(
port=port,
server_name=server_name,
upstream_name=upstream_name,
upstream_config=upstream_config
)
# Пример использования
servers = ["192.168.1.10:8080", "192.168.1.11:8080", "192.168.1.12:8080"]
config = generate_nginx_config("api.example.com", 80, servers)
print(config)
Шаг 3: Работа с API и JSON-форматированием
import json
import requests
def format_api_response(endpoint, response_data):
"""Красивое форматирование API-ответов для логов"""
status_code = response_data.get('status_code', 'Unknown')
response_time = response_data.get('response_time', 0)
# Цветовое кодирование статусов
status_emoji = {
200: "✅",
201: "✅",
400: "⚠️",
401: "🔐",
403: "🚫",
404: "❌",
500: "🔥"
}.get(status_code, "❓")
return f"{status_emoji} {endpoint} | Status: {status_code} | Time: {response_time:.3f}s"
# Пример мониторинга API
def monitor_endpoints(endpoints):
for endpoint in endpoints:
try:
start_time = time.time()
response = requests.get(endpoint, timeout=5)
response_time = time.time() - start_time
result = {
'status_code': response.status_code,
'response_time': response_time
}
print(format_api_response(endpoint, result))
except Exception as e:
print(f"🔥 {endpoint} | Error: {str(e)}")
# Использование
endpoints = [
"https://api.example.com/health",
"https://api.example.com/status",
"https://api.example.com/metrics"
]
monitor_endpoints(endpoints)
Сравнение методов форматирования
Метод | Производительность | Читаемость | Гибкость | Рекомендации |
---|---|---|---|---|
% форматирование | Средняя | Низкая | Ограниченная | Только для legacy-кода |
str.format() | Хорошая | Хорошая | Высокая | Для шаблонов и сложного форматирования |
f-strings | Отличная | Отличная | Высокая | Для современного кода (Python 3.6+) |
Template strings | Низкая | Хорошая | Безопасная | Для пользовательских шаблонов |
Продвинутые техники и практические кейсы
Условное форматирование в f-strings
def format_server_status(server_data):
"""Условное форматирование статуса сервера"""
name = server_data['name']
cpu = server_data['cpu']
memory = server_data['memory']
status = server_data['status']
# Условное форматирование прямо в f-string
return f"""
Server: {name}
Status: {status.upper() if status == 'online' else f'🔴 {status.upper()}'}
CPU: {cpu}% {'🔥' if cpu > 90 else '⚠️' if cpu > 70 else '✅'}
Memory: {memory}% {'🔥' if memory > 90 else '⚠️' if memory > 80 else '✅'}
Load: {'HIGH' if cpu > 80 or memory > 80 else 'NORMAL'}
"""
# Пример данных
servers = [
{'name': 'web-01', 'cpu': 45.2, 'memory': 67.8, 'status': 'online'},
{'name': 'db-01', 'cpu': 89.5, 'memory': 95.2, 'status': 'warning'},
{'name': 'cache-01', 'cpu': 23.1, 'memory': 45.6, 'status': 'offline'}
]
for server in servers:
print(format_server_status(server))
Форматирование таблиц и отчётов
def generate_server_report(servers_data):
"""Генерация табличного отчёта о серверах"""
header = f"{'Name':<15} {'Status':<10} {'CPU':<8} {'Memory':<8} {'Uptime':<10}"
separator = "-" * len(header)
print(header)
print(separator)
for server in servers_data:
name = server['name']
status = server['status']
cpu = f"{server['cpu']:.1f}%"
memory = f"{server['memory']:.1f}%"
uptime = f"{server['uptime']}d"
# Выравнивание колонок
row = f"{name:<15} {status:<10} {cpu:<8} {memory:<8} {uptime:<10}"
print(row)
# Пример использования
servers_data = [
{'name': 'web-01', 'status': 'online', 'cpu': 45.2, 'memory': 67.8, 'uptime': 15},
{'name': 'web-02', 'status': 'online', 'cpu': 52.1, 'memory': 71.3, 'uptime': 12},
{'name': 'db-01', 'status': 'warning', 'cpu': 89.5, 'memory': 95.2, 'uptime': 8},
]
generate_server_report(servers_data)
Безопасное форматирование с Template strings
from string import Template
def safe_email_template(template_string, user_data):
"""Безопасное форматирование email-шаблонов"""
template = Template(template_string)
try:
return template.safe_substitute(user_data)
except KeyError as e:
print(f"Отсутствует переменная: {e}")
return None
# Пример шаблона для уведомлений о сервере
email_template = """
Subject: Server Alert - $server_name
Dear $admin_name,
Server $server_name is experiencing issues:
- CPU Usage: $cpu_usage%
- Memory Usage: $memory_usage%
- Status: $status
Please investigate immediately.
Best regards,
Monitoring System
"""
# Данные для подстановки
alert_data = {
'server_name': 'production-web-01',
'admin_name': 'John Doe',
'cpu_usage': 95.5,
'memory_usage': 87.2,
'status': 'Critical'
}
email_content = safe_email_template(email_template, alert_data)
print(email_content)
Интеграция с другими инструментами
Форматирование для Slack уведомлений
import json
import requests
def send_slack_alert(webhook_url, server_data):
"""Отправка красиво отформатированного уведомления в Slack"""
# Эмодзи для статусов
status_emoji = {
'ok': ':white_check_mark:',
'warning': ':warning:',
'critical': ':rotating_light:',
'offline': ':x:'
}
status = server_data['status']
emoji = status_emoji.get(status, ':question:')
# Форматирование сообщения для Slack
message = f"""
{emoji} *Server Alert: {server_data['name']}*
*Status:* {status.upper()}
*CPU:* {server_data['cpu']}%
*Memory:* {server_data['memory']}%
*Disk:* {server_data['disk']}%
*Timestamp:* {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
payload = {
'text': message,
'username': 'ServerBot',
'icon_emoji': ':robot_face:'
}
response = requests.post(webhook_url, json=payload)
return response.status_code == 200
# Пример использования
server_alert = {
'name': 'production-api-01',
'status': 'critical',
'cpu': 95.8,
'memory': 89.2,
'disk': 76.5
}
# send_slack_alert('YOUR_WEBHOOK_URL', server_alert)
Генерация Dockerfile с параметрами
def generate_dockerfile(app_config):
"""Генерация Dockerfile с параметрами"""
dockerfile_template = """FROM {base_image}
LABEL maintainer="{maintainer}"
LABEL version="{version}"
WORKDIR /app
# Install dependencies
{install_commands}
# Copy application
COPY . /app
# Set environment variables
{env_variables}
# Expose port
EXPOSE {port}
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
CMD curl -f http://localhost:{port}/health || exit 1
# Run application
CMD ["{start_command}"]
"""
# Форматирование команд установки
install_commands = "\n".join([f"RUN {cmd}" for cmd in app_config['install_commands']])
# Форматирование переменных окружения
env_variables = "\n".join([f"ENV {k}={v}" for k, v in app_config['env_vars'].items()])
return dockerfile_template.format(
base_image=app_config['base_image'],
maintainer=app_config['maintainer'],
version=app_config['version'],
install_commands=install_commands,
env_variables=env_variables,
port=app_config['port'],
start_command=app_config['start_command']
)
# Пример конфигурации
app_config = {
'base_image': 'python:3.9-slim',
'maintainer': 'devops@example.com',
'version': '1.0.0',
'install_commands': [
'apt-get update',
'apt-get install -y curl',
'pip install --no-cache-dir -r requirements.txt'
],
'env_vars': {
'PYTHONPATH': '/app',
'FLASK_ENV': 'production',
'DATABASE_URL': 'postgresql://localhost/myapp'
},
'port': 8080,
'start_command': 'python app.py'
}
dockerfile_content = generate_dockerfile(app_config)
print(dockerfile_content)
Автоматизация и интеграция в CI/CD
Форматирование строк особенно полезно при создании скриптов для CI/CD пайплайнов:
#!/usr/bin/env python3
import os
import subprocess
import datetime
def deploy_notification(deployment_info):
"""Уведомление о деплое с детальной информацией"""
deploy_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# Получение информации о git commit
try:
commit_hash = subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode().strip()[:8]
commit_message = subprocess.check_output(['git', 'log', '-1', '--pretty=%B']).decode().strip()
author = subprocess.check_output(['git', 'log', '-1', '--pretty=%an']).decode().strip()
except:
commit_hash = "unknown"
commit_message = "No git info available"
author = "unknown"
# Форматирование уведомления
notification = f"""
🚀 **DEPLOYMENT NOTIFICATION** 🚀
**Environment:** {deployment_info['environment']}
**Service:** {deployment_info['service_name']}
**Version:** {deployment_info['version']}
**Status:** {deployment_info['status']}
**Git Information:**
- Commit: {commit_hash}
- Author: {author}
- Message: {commit_message}
**Deployment Details:**
- Started: {deployment_info['start_time']}
- Completed: {deploy_time}
- Duration: {deployment_info['duration']}s
**Server:** {deployment_info['server_url']}
**Health Check:** {deployment_info['health_check_url']}
---
Deployed by: {os.getenv('USER', 'CI/CD System')}
"""
return notification
# Пример использования в CI/CD скрипте
deployment_info = {
'environment': 'production',
'service_name': 'api-service',
'version': 'v1.2.3',
'status': 'SUCCESS',
'start_time': '2024-01-15 14:30:00',
'duration': 45,
'server_url': 'https://api.example.com',
'health_check_url': 'https://api.example.com/health'
}
print(deploy_notification(deployment_info))
Для тех, кто разрабатывает и развёртывает такие скрипты, рекомендую использовать качественные VPS серверы для тестирования, а для production-окружения — выделенные серверы с гарантированными ресурсами.
Производительность и оптимизация
Интересный факт: f-strings не только самые читаемые, но и самые быстрые. Вот сравнение производительности:
import timeit
# Тест производительности различных методов
def benchmark_formatting():
name = "server-01"
cpu = 75.5
memory = 68.2
# % форматирование
def percent_format():
return "Server %s: CPU %.1f%%, Memory %.1f%%" % (name, cpu, memory)
# str.format()
def str_format():
return "Server {}: CPU {:.1f}%, Memory {:.1f}%".format(name, cpu, memory)
# f-strings
def f_string():
return f"Server {name}: CPU {cpu:.1f}%, Memory {memory:.1f}%"
# Бенчмарк
methods = [
("% formatting", percent_format),
("str.format()", str_format),
("f-strings", f_string)
]
for method_name, method_func in methods:
time_taken = timeit.timeit(method_func, number=100000)
print(f"{method_name}: {time_taken:.4f} seconds")
# Запуск бенчмарка
benchmark_formatting()
Результаты показывают, что f-strings примерно в 2-3 раза быстрее str.format() и на 20-30% быстрее % форматирования.
Полезные ссылки и ресурсы
- Официальная документация Python по форматированию строк
- PEP 498 — Literal String Interpolation
- Template strings в Python
- Real Python Guide on String Formatting
Выводы и рекомендации
Форматирование строк в Python 3 — это не просто способ склеить текст, а мощный инструмент для создания читаемого, поддерживаемого кода. Вот мои рекомендации:
- Используйте f-strings для всего нового кода — они быстрые, читаемые и поддерживают сложные выражения
- str.format() отлично подходит для шаблонов — особенно когда нужно переиспользовать формат с разными данными
- Template strings для безопасности — когда работаете с пользовательским вводом или конфигурационными файлами
- Избегайте % форматирования — оставьте его только для legacy-кода
В серверной разработке правильное форматирование строк поможет вам создавать понятные логи, генерировать конфигурационные файлы, формировать отчёты и уведомления. Это одна из тех базовых техник, которая делает разницу между кодом новичка и профессионала.
Помните: код читается чаще, чем пишется. Потратьте время на красивое форматирование сейчас — сэкономите часы на отладке потом. И не забывайте про производительность: f-strings не только красивее, но и быстрее!
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.