Основы написания сценариев: работа с Python скриптами

Раздел: Основы Python -> Работа со скриптами Python

Создание скрипта на Python

Наиболее универсальный подход к написанию скрипта предполагает использование функции main в сочетании с модулем argparse для обработки аргументов командной строки. Это обеспечивает гибкость, удобство тестирования и обработку ошибок. Такой скрипт легко адаптировать под разные задачи.

import argparse
import sys

def main():
    parser = argparse.ArgumentParser(
        description='Универсальный скрипт для обработки файлов'
    )
    parser.add_argument('input', help='Путь к входному файлу')
    parser.add_argument('--output', '-o', default='output.txt',
                        help='Путь к выходному файлу (по умолч. output.txt)')
    parser.add_argument('--upper', action='store_true',
                        help='Преобразовать текст в верхний регистр')
    args = parser.parse_args()

    try:
        with open(args.input, 'r', encoding='utf-8') as f:
            data = f.read()
    except FileNotFoundError:
        print(f'Ошибка: файл \'{args.input}\' не найден', file=sys.stderr)
        sys.exit(1)
    except PermissionError:
        print(f'Ошибка: недостаточно прав для чтения файла', file=sys.stderr)
        sys.exit(1)

    if args.upper:
        data = data.upper()

    with open(args.output, 'w', encoding='utf-8') as f:
        f.write(data)
    print(f'Результат сохранен в {args.output}')

if __name__ == '__main__':
    main()

писать скрипт python (написание скрипта на python)

Пояснения: Скрипт начинается с импорта необходимых модулей. В функции main создается парсер, который ожидает обязательный аргумент input и опциональные --output и --upper. После разбора аргументов выполняется чтение файла с обработкой возможных ошибок (файл не найден, нет прав). Затем, если указан флаг --upper, текст преобразуется в верхний регистр. Результат записывается в выходной файл. Конструкция if __name__ == '__main__' гарантирует, что код выполняется только при запуске скрипта напрямую, а не при импорте.

Типичные проблемы и их решение:

  • Забытая проверка __name__: если её опустить, код выполнится при импорте модуля. Решение: всегда добавлять эту конструкцию.
  • Неправильная кодировка: при открытии файла без указания encoding='utf-8' на некоторых системах возникает ошибка. Решение: всегда явно указывать кодировку.
  • Отсутствие shebang: в Unix-подобных системах скрипт может не запускаться напрямую без указания интерпретатора. Добавьте в начало файла #!/usr/bin/env python3.

Как написать простейший скрипт без аргументов?

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

print('Привет, мир!')
result = sum(range(100))
print(f'Сумма чисел от 0 до 99: {result}')

Цель использования: быстрое выполнение простых операций без необходимости ввода данных.

Проблемы:

  • Глобальные переменные: код выполняется в глобальной области, что затрудняет повторное использование функций. Решение: помещать логику в функции.
  • Отсутствие проверки на прямой запуск: при импорте такого модуля код выполнится непреднамеренно. Решение: добавить блок if __name__ == '__main__'.

Как обрабатывать аргументы командной строки без установки дополнительных модулей?

Встроенный модуль sys.argv позволяет получить список аргументов. Это простейший способ, но с ограниченной функциональностью.

import sys

if len(sys.argv) < 2:
    print('Использование: script.py имя_файла', file=sys.stderr)
    sys.exit(1)

filename = sys.argv[1]
print(f'Выбран файл: {filename}')

Цель использования: быстрый прототип или скрипт с минимальными требованиями к парсингу.

Проблемы:

  • Ручная проверка количества аргументов: легко допустить ошибку индексации. Решение: использовать argparse.
  • Отсутствие поддержки именованных аргументов: сложно обрабатывать флаги типа --verbose. Решение: парсить вручную или перейти на argparse.

Как загрузить настройки из конфигурационного файла?

Модуль configparser позволяет читать INI-подобные файлы. Это удобно для скриптов с большим количеством параметров.

import configparser
config = configparser.ConfigParser()
config.read('config.ini')
try:
    host = config['DEFAULT']['host']
    port = config.getint('DEFAULT', 'port')
except KeyError as e:
    print(f'Ошибка конфигурации: отсутствует {e}', file=sys.stderr)
    sys.exit(1)
print(f'Подключение к {host}:{port}')

Цель использования: централизованное хранение настроек, возможность менять параметры без изменения кода.

Проблемы:

  • Некорректный синтаксис INI: например, отсутствие секций. Решение: проверять файл перед чтением.
  • Типы данных: configparser возвращает строки, требуется приведение типов. Решение: использовать методы getint, getfloat.

Как получить данные от пользователя во время выполнения скрипта?

Функция input() позволяет организовать диалог. Применяется в обучающих программах или интерактивных утилитах.

name = input('Введите ваше имя: ')
age = int(input('Введите ваш возраст: '))
print(f'Привет, {name}! Через год вам будет {age + 1}.')

Цель использования: сценарии, где данные вводятся вручную, например, калькуляторы или простые игры.

Проблемы:

  • Некорректный ввод: если пользователь введет не число, возникнет исключение ValueError. Решение: обернуть в try/except.
  • Прерывание ввода (EOF): при перенаправлении stdin может возникнуть EOFError. Решение: обрабатывать эту ошибку.

Как использовать сторонние библиотеки в скрипте и управлять зависимостями?

В современной разработке скрипты часто полагаются на внешние пакеты. Например, библиотека requests для HTTP-запросов. Для управления зависимостями используется файл requirements.txt.

import requests
import sys

def fetch_url(url):
    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status()
        return response.text
    except requests.exceptions.RequestException as e:
        print(f'Ошибка при запросе: {e}', file=sys.stderr)
        sys.exit(1)

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Использование: script.py URL')
        sys.exit(1)
    content = fetch_url(sys.argv[1])
    print(content[:200])  # первые 200 символов

Пример requirements.txt:

requests>=2.28.0

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

Проблемы:

  • Модуль не установлен: пользователь получит ModuleNotFoundError. Решение: перед запуском выполнить pip install -r requirements.txt или добавить проверку в код.
  • Конфликт версий: разные проекты могут требовать разные версии одной библиотеки. Решение: использовать виртуальное окружение (venv).

Расширенные примеры скриптов на Python

Скрипт для скачивания файлов с индикатором прогресса

В этом примере используется библиотека tqdm для отображения прогресса загрузки. Такой скрипт удобен для автоматизации загрузок из сети.

Пример
import argparse
import requests
from tqdm import tqdm

def download_file(url, dest):
    response = requests.get(url, stream=True)
    response.raise_for_status()
    total_size = int(response.headers.get('content-length', 0))
    with open(dest, 'wb') as file, tqdm(
        desc=dest,
        total=total_size,
        unit='B',
        unit_scale=True,
        unit_divisor=1024
    ) as pbar:
        for chunk in response.iter_content(chunk_size=8192):
            file.write(chunk)
            pbar.update(len(chunk))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('url', help='ссылка на файл')
    parser.add_argument('dest', help='путь для сохранения')
    args = parser.parse_args()
    download_file(args.url, args.dest)
    print('Загрузка завершена')

Результат выполнения (пример вывода):

downloaded_file.zip: 100%|██████████| 2.34M/2.34M [00:02<00:00, 1.11MB/s]
Загрузка завершена

Скрипт для анализа данных из CSV

Этот скрипт читает CSV файл, подсчитывает частоту значений в указанном столбце и выводит топ результатов. Применяется для быстрого исследования данных.

Пример
import csv
import sys
import collections
import argparse

def analyze_csv(filepath, column_index):
    counter = collections.Counter()
    try:
        with open(filepath, 'r', encoding='utf-8') as f:
            reader = csv.reader(f)
            for row in reader:
                if len(row) > column_index:
                    counter[row[column_index]] += 1
    except FileNotFoundError:
        print(f'Файл {filepath} не найден', file=sys.stderr)
        sys.exit(1)
    return counter.most_common(10)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('file', help='путь к CSV файлу')
    parser.add_argument('--column', '-c', type=int, default=0,
                        help='индекс столбца (по умолчанию 0)')
    args = parser.parse_args()
    top = analyze_csv(args.file, args.column)
    for value, count in top:
        print(f'{value}: {count}')

Результат выполнения (пример вывода):

Иванов: 34
Петров: 28
Сидоров: 22
...

Скрипт с подкомандами (субпарсеры argparse)

Позволяет реализовать интерфейс командной строки с несколькими командами, как у утилит git или apt. Каждая команда имеет свои аргументы.

Пример
import argparse

def cmd_add(args):
    print(f'Сложение: {args.x} + {args.y} = {args.x + args.y}')

def cmd_subtract(args):
    print(f'Вычитание: {args.x} - {args.y} = {args.x - args.y}')

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='command', required=True)

    add_parser = subparsers.add_parser('add', help='сложение двух чисел')
    add_parser.add_argument('x', type=int)
    add_parser.add_argument('y', type=int)
    add_parser.set_defaults(func=cmd_add)

    sub_parser = subparsers.add_parser('sub', help='вычитание')
    sub_parser.add_argument('x', type=int)
    sub_parser.add_argument('y', type=int)
    sub_parser.set_defaults(func=cmd_subtract)

    args = parser.parse_args()
    args.func(args)

Примеры запуска:

python script.py add 5 3
Сложение: 5 + 3 = 8

python script.py sub 10 4
Вычитание: 10 - 4 = 6

Асинхронный скрипт для параллельных HTTP-запросов

Использование asyncio и aiohttp позволяет эффективно выполнять множество запросов одновременно. Идеально для парсинга или тестирования API.

Пример
import asyncio
import aiohttp
import argparse

async def fetch(session, url):
    try:
        async with session.get(url, timeout=10) as response:
            return await response.text()
    except Exception as e:
        return f'Ошибка: {e}'

async def main(urls):
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
    for url, result in zip(urls, results):
        print(f'{url}: {len(result)} символов')

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('urls', nargs='+', help='список URL')
    args = parser.parse_args()
    asyncio.run(main(args.urls))

Результат выполнения (пример вывода):

https://example.com: 1250 символов
https://httpbin.org/get: 312 символов
...

Скрипт для работы с внешним API (погода)

Демонстрирует получение данных от OpenWeatherMap, обработку JSON и вывод информации. Требуется API-ключ, передаваемый через аргумент или переменную окружения.

Пример
import argparse
import requests
import os

def get_weather(city, api_key):
    url = 'http://api.openweathermap.org/data/2.5/weather'
    params = {
        'q': city,
        'appid': api_key,
        'units': 'metric'
    }
    try:
        response = requests.get(url, params=params, timeout=5)
        response.raise_for_status()
        data = response.json()
        temp = data['main']['temp']
        description = data['weather'][0]['description']
        print(f'В городе {city}: {temp}°C, {description}')
    except requests.exceptions.RequestException as e:
        print(f'Ошибка запроса: {e}', file=sys.stderr)
        sys.exit(1)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('city', help='название города')
    parser.add_argument('--key', help='API-ключ (если не указан, берется из переменной WEATHER_API_KEY)')
    args = parser.parse_args()
    api_key = args.key or os.environ.get('WEATHER_API_KEY')
    if not api_key:
        print('Не указан API-ключ', file=sys.stderr)
        sys.exit(1)
    get_weather(args.city, api_key)

Результат выполнения (пример вывода):

В городе Москва: 5.2°C, облачно с прояснениями

Написание скрипта на Python - comments

En
писать скрипт python (python)