116 lines
3.8 KiB
Python
116 lines
3.8 KiB
Python
# -*- 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() |