Решение повседневных задач с помощью Python: примеры и код
Основные рутинные задачи и их автоматизация
Как переименовать все файлы в папке с добавлением префикса?
Эффективное решение с pathlib
from pathlib import Path
folder = Path('папка')
for file in folder.iterdir():
if file.is_file():
new_name = f'prefix_{file.name}'
file.rename(folder / new_name)рутинные задачи python (рутинные задачи на python)
Модуль pathlib предоставляет объектно-ориентированный интерфейс для работы с путями. Метод iterdir() возвращает итератор по содержимому папки, а rename() позволяет переименовать файл. Пример добавляет префикс prefix_ ко всем файлам в указанной папке. Данный подход работает на Windows, Linux и macOS без дополнительных настроек.
Вариант с os.rename
import os
folder = 'папка'
for filename in os.listdir(folder):
full_path = os.path.join(folder, filename)
if os.path.isfile(full_path):
new_name = f'prefix_{filename}'
os.rename(full_path, os.path.join(folder, new_name))
Когда использовать:
Если требуется совместимость со старыми версиями Python (до 3.4) или привычный стиль C. Однако os.listdir не различает файлы и папки, поэтому нужна явная проверка os.path.isfile. В современных проектах предпочтительнее pathlib.
Типичные ошибки
- FileExistsError возникает, если целевой файл уже существует. Решение: проверять наличие с Path.exists() или генерировать уникальное имя.
- PermissionError при отсутствии прав на запись в папку. Решение: запускать скрипт с соответствующими правами или изменить права доступа.
- FileNotFoundError если исходный файл был удалён во время выполнения. Решение: обрабатывать исключения или использовать итерацию по копии списка.
Как обработать данные из CSV-файла и отфильтровать строки по условию?
Эффективное решение с pandas
import pandas as pd
df = pd.read_csv('data.csv')
filtered = df[df['age'] > 25]
filtered.to_csv('filtered.csv', index=False)
Библиотека pandas позволяет загрузить CSV в DataFrame, отфильтровать строки по значению столбца (например, возраст больше 25) и сохранить результат. Параметр index=False предотвращает запись номера строки в выходной файл. Это решение подходит для файлов любого размера, так как pandas оптимизирован для работы с табличными данными.
Вариант с встроенным модулем csv
import csv
with open('data.csv', newline='', encoding='utf-8') as f:
reader = csv.DictReader(f)
with open('filtered.csv', 'w', newline='', encoding='utf-8') as out:
writer = csv.DictWriter(out, fieldnames=reader.fieldnames)
writer.writeheader()
for row in reader:
if int(row['age']) > 25:
writer.writerow(row)
Когда использовать:
Модуль csv не требует установки дополнительных библиотек и работает быстрее на маленьких файлах. Однако для больших объёмов данных или сложной фильтрации pandas даёт более лаконичный код и дополнительные возможности (группировка, агрегация).
Типичные ошибки
- UnicodeDecodeError при несовпадении кодировки. Решение: явно указать encoding='utf-8-sig' или определить кодировку с помощью chardet.
- ValueError при сравнении числа со строкой, если столбец не был приведён к числовому типу. Решение: использовать pd.to_numeric() или обернуть в int() после чтения.
- FileNotFoundError при неверном пути. Решение: использовать абсолютные пути или проверять существование файла.
Как отправить электронное письмо с вложением?
Эффективное решение с smtplib и email
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders
msg = MIMEMultipart()
msg['From'] = 'sender@example.com'
msg['To'] = 'recipient@example.com'
msg['Subject'] = 'Тема письма'
body = MIMEText('Текст письма', 'plain')
msg.attach(body)
filename = 'document.pdf'
with open(filename, 'rb') as f:
part = MIMEBase('application', 'octet-stream')
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename={filename}')
msg.attach(part)
with smtplib.SMTP('smtp.example.com', 587) as server:
server.starttls()
server.login('user', 'password')
server.send_message(msg)
Библиотеки smtplib и email позволяют создать MIME-письмо с произвольными вложениями. TLS-шифрование обеспечивается вызовом starttls(). Для отправки через Gmail требуется пароль приложения или OAuth2.
Вариант с yagmail
import yagmail
yag = yagmail.SMTP('user', 'password')
yag.send(to='recipient@example.com',
subject='Тема письма',
contents='Текст письма',
attachments='document.pdf')
Когда использовать:
yagmail упрощает код для стандартных сценариев (одно письмо, несколько вложений). Однако он менее гибок для кастомизации MIME-заголовков и не поддерживает некоторые почтовые серверы без дополнительной настройки.
Типичные ошибки
- SMTPAuthenticationError при неверных учётных данных. Решение: проверить логин/пароль, для Gmail включить доступ для ненадёжных приложений или использовать пароль приложения.
- TimeoutError при недоступности SMTP-сервера. Решение: проверить имя хоста и порт, добавить таймаут.
- FileNotFoundError при отсутствии файла вложения. Решение: предварительно проверять существование файла.
Как извлечь данные из HTML-страницы?
Эффективное решение с requests и BeautifulSoup
import requests
from bs4 import BeautifulSoup
url = 'https://example.com'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
titles = soup.find_all('h2', class_='title')
for t in titles:
print(t.get_text(strip=True))
Библиотека requests выполняет HTTP-запрос, а BeautifulSoup парсит HTML. Поиск элементов осуществляется с помощью find_all с указанием тега и класса. Этот метод подходит для статических страниц без JavaScript.
Вариант с lxml
from lxml import html
import requests
resp = requests.get('https://example.com')
tree = html.fromstring(resp.content)
titles = tree.xpath('//h2[@class="title"]/text()')
for t in titles:
print(t.strip())
Когда использовать:
lxml быстрее парсит большие документы и поддерживает XPath. Однако его установка может потребовать системные библиотеки (libxml2). Для простых задач BeautifulSoup удобнее благодаря устойчивости к некорректной разметке.
Типичные ошибки
- requests.exceptions.ConnectionError при отсутствии интернет-соединения или неверном URL. Решение: проверять статус ответа (response.raise_for_status()).
- AttributeError при обращении к методу find_all на None. Решение: убедиться, что страница загружена, и обрабатывать случаи отсутствия элементов.
- UnicodeDecodeError при неверной кодировке. Решение: указать response.encoding или использовать response.content.
Расширенные примеры автоматизации
Рекурсивное переименование файлов с заменой пробелов
Цель:
Заменить все пробелы в именах файлов на подчёркивания во всех подпапках (рекурсивно).
from pathlib import Path
for file in Path('.').rglob('*'):
if file.is_file() and ' ' in file.name:
new_name = file.name.replace(' ', '_')
file.rename(file.parent / new_name)
Файлы переименованы: 'my file.txt' -> 'my_file.txt', 'data report.csv' -> 'data_report.csv'
Метод rglob('*') обходит все файлы и папки рекурсивно. Проверка is_file() исключает директории.
Обработка CSV с большим объёмом данных (построчное чтение)
Цель:
Отфильтровать строки в CSV размером более 1 ГБ, не загружая весь файл в память.
import csv
with open('large.csv', newline='', encoding='utf-8') as inf:
reader = csv.DictReader(inf)
with open('filtered_large.csv', 'w', newline='', encoding='utf-8') as outf:
writer = csv.DictWriter(outf, fieldnames=reader.fieldnames)
writer.writeheader()
for row in reader:
if int(row['amount']) > 1000:
writer.writerow(row)
Создан файл 'filtered_large.csv' с отфильтрованными строками. Потребление памяти минимально.
Встроенный модуль csv читает строки последовательно, поэтому даже огромные файлы обрабатываются без перегрузки RAM.
Отправка писем с HTML-содержимым и несколькими вложениями
Цель:
Сформировать письмо с HTML-оформлением и прикрепить два файла.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
msg = MIMEMultipart('alternative')
msg['From'] = 'sender@example.com'
msg['To'] = 'recipient@example.com'
msg['Subject'] = 'Отчёт за месяц'
html = '''
<html>
<body>
<h2>Ежемесячный отчёт</h2>
<p>Сумма продаж: <b>1 000 000</b> руб.</p>
</body>
</html>'''
part_html = MIMEText(html, 'html')
msg.attach(part_html)
for file in ['report.pdf', 'chart.png']:
with open(file, 'rb') as f:
part = MIMEBase('application', 'octet-stream')
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename={file}')
msg.attach(part)
with smtplib.SMTP('smtp.example.com', 587) as server:
server.starttls()
server.login('user', 'password')
server.send_message(msg)
Письмо отправлено с HTML-версией и двумя файлами. Получатель видит форматированный текст.
Тип MIME 'alternative' позволяет одновременно передавать текстовую и HTML-версии. Вложения добавляются как отдельные MIME-части.
Парсинг динамического контента с помощью Selenium
Цель:
Извлечь данные со страницы, которая подгружается через JavaScript после загрузки DOM.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
driver = webdriver.Chrome()
driver.get('https://example.com/dynamic')
elements = driver.find_elements(By.CSS_SELECTOR, '.item-title')
for el in elements:
print(el.text)
driver.quit()
Вывод: 'Название товара 1', 'Название товара 2', ...
Selenium управляет браузером и ждёт выполнения JavaScript. Для ускорения можно использовать headless-режим: добавить options.add_argument('--headless').