# -*- coding: utf-8 -*- """Лабораторная 0: проверка готовности окружения. Запуск из корня курса: python lab00_intro/check_env.py Скрипт проверяет версию Python, библиотеки, число ядер и работоспособность threading / multiprocessing / asyncio. Все проверки должны напечатать [OK]. """ import os import sys # делаем доступным импорт common.* при запуске из корня курса sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) FAILED = [] def check(name: str, fn): try: detail = fn() print(f"[OK] {name}{(': ' + str(detail)) if detail else ''}") except Exception as e: # noqa: BLE001 FAILED.append(name) print(f"[FAIL] {name}: {type(e).__name__}: {e}") def check_python_version(): v = sys.version_info assert v >= (3, 10), f"нужен Python 3.10+, у вас {v.major}.{v.minor}" return f"Python {v.major}.{v.minor}.{v.micro}" def check_modules(): import numpy import matplotlib import pytest return (f"numpy {numpy.__version__}, matplotlib {matplotlib.__version__}, " f"pytest {pytest.__version__}") def check_cpu_count(): import multiprocessing n = multiprocessing.cpu_count() assert n >= 2, "нужно минимум 2 логических ядра" return f"{n} логических ядер" def check_threading(): from concurrent.futures import ThreadPoolExecutor results = [] with ThreadPoolExecutor(max_workers=4) as pool: results = list(pool.map(lambda x: x * x, range(8))) assert results == [i * i for i in range(8)] return "ThreadPoolExecutor работает" def _double(x): """Функция модульного уровня — Pool требует пиккелируемость.""" return x * 2 def check_multiprocessing(): import multiprocessing ctx = multiprocessing.get_context() # spawn на Windows, fork на macOS/Linux with ctx.Pool(2) as pool: res = pool.map(_double, [1, 2, 3, 4]) assert res == [2, 4, 6, 8], res return f"метод запуска: {ctx.get_start_method()}" def check_asyncio(): import asyncio async def main(): await asyncio.sleep(0.01) return 42 assert asyncio.run(main()) == 42 return "event loop работает" def check_common_tasks(): from common.tasks import get_variant v = get_variant(1) assert "task_name" in v and "io" in v return f"вариант 1: {v['describe']}" def main(): print("=" * 60) print("Проверка окружения для курса «Технология параллельного программирования»") print("=" * 60) check("Версия Python", check_python_version) check("Библиотеки", check_modules) check("Число ядер CPU", check_cpu_count) check("Потоки (threading)", check_threading) check("Процессы (multiprocessing)", check_multiprocessing) check("Асинхронность (asyncio)", check_asyncio) check("Банк задач (common.tasks)", check_common_tasks) print("-" * 60) if FAILED: print(f"ПРОБЛЕМЫ: {', '.join(FAILED)}") print("Разберитесь по методичке lab00_intro/методичка.md — без этого") print("следующие лабораторные не будут работать.") sys.exit(1) print("Всё готово. Запомните свой вариант из common/варианты.md.") if os.name == "nt": print("(Кириллица отображается кракозябрами? Выполните: chcp 65001)") if __name__ == "__main__": main()