Решение повседневных задач с помощью Python: примеры и код

Раздел: 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').

Рутинные задачи на Python - comments

En
рутинные задачи python (python)