Основы написания сценариев: работа с 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, облачно с прояснениями