🔝 الدليل الرئيسي للسلسلة: بايثون: لغة ومنظومة وأطر للمطوّرين
تأرجحت أدوات Python في 2026. أصدرت Astral، الناشر خلف Ruff، أداة uv في 2024 وثبّتت المنظومة في كدسة متماسكة: uv يحل محل pip + virtualenv + pip-tools + pyenv + poetry بثنائي Rust واحد، وruff يحل محل flake8 + black + isort + pydocstyle + pyupgrade بـ linter+formatter Rust واحد. المكسب جذري: مشروع يستغرق 45 ثانية لتثبيت تبعياته بـ pip يُثبَّت في ثانيتين مع uv. linter يستغرق 8 ثوانٍ مع flake8 يعمل في 200 ms مع Ruff. يُثبّت هذا الدرس ويُعدّ الاثنين لسير عمل احترافي في 2026.
المتطلبات
- Python 3.13.13 أو 3.14.5 متوفر محليًا (راجع تثبيت Python 3) — اختياري، uv يستطيع تثبيته بنفسه
- طرفية (zsh، bash أو PowerShell)
- مشروع موجود أو نية إنشاء جديد
- الوقت المُقدَّر: 60 دقيقة
الخطوة 1 — تثبيت uv (مستقل، مبني بـ Rust)
uv 0.11.14 صدر في 12 مايو 2026. التثبيت عبر سكربت مستقل لا يحتاج Python مُسبق التثبيت (uv ثنائي Rust مستقل).
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows PowerShell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
uv --version
# uv 0.11.14
uv self update
الثنائي يُثبَّت في ~/.local/bin/uv (Linux/macOS) أو %LOCALAPPDATA%/uv/bin/uv.exe (Windows) ويُضاف تلقائيًا لـ PATH بعد إعادة تشغيل shell. في هذه المرحلة، uv جاهز لإدارة Python نفسه: uv python install 3.14 يُحمّل المفسّر الرسمي دون لمس النظام.
الخطوة 2 — إنشاء مشروع بـ uv init
uv init يُهيئ مشروعًا نظيفًا: pyproject.toml أدنى، .python-version، بيئة افتراضية، هيكل ملفات.
uv init mon-service --python 3.14
cd mon-service
uv add httpx pydantic
uv add --dev pytest pytest-cov ruff
uv sync
uv run python -c "import httpx; print(httpx.__version__)"
uv run pytest
ثلاثة فروق رئيسية مع poetry/pip-tools. الـ uv.lock يُولَّد تلقائيًا وحتميًا: حتى على Mac M2 وrunner Linux x86_64، الإصدارات المحلولة متطابقة. uv sync يُنشئ ويُزامن .venv في ثوانٍ. uv run يُنفّذ أمرًا في venv دون الحاجة لتفعيله يدويًا.
الخطوة 3 — إعداد pyproject.toml مع uv
uv يتبع PEP 621 (project metadata موحد) ويمدّد بخياراته الخاصة تحت [tool.uv].
[project]
name = "mon-service"
version = "0.1.0"
description = "Service API en Python 3.14"
requires-python = ">=3.13,<3.15"
dependencies = [
"httpx>=0.27,<1.0",
"pydantic>=2.13,<3.0",
"fastapi>=0.136",
]
[project.optional-dependencies]
postgres = ["asyncpg>=0.30", "sqlalchemy[asyncio]>=2.0"]
redis = ["redis>=5.0"]
[dependency-groups]
dev = [
"pytest>=9.0",
"pytest-cov>=7.1",
"pytest-asyncio>=1.3",
"ruff>=0.13",
"mypy>=1.13",
]
[tool.uv]
package = true
default-groups = ["dev"]
managed = true
requires-python = ">=3.13,<3.15" انضباط هيكلي: يُفشل uv sync على Python غير متوافق. الـ extras يُتيحان تثبيت الحد الأدنى (uv sync) أو الإثراء (uv sync --extra postgres --extra redis). dependency-groups (PEP 735) يحلّان محل dev extras المُسيء.
الخطوة 4 — تثبيت وإعداد Ruff
Ruff يدمج linter وformatter. إعداده يعيش في pyproject.toml تحت [tool.ruff].
[tool.ruff]
line-length = 100
target-version = "py314"
src = ["src", "tests"]
extend-exclude = ["migrations", "vendor"]
[tool.ruff.lint]
select = [
"E", "W", "F", "I", "B", "C4", "UP", "N", "S", "SIM", "RUF",
]
ignore = [
"E501", # line too long — géré par le formatter
"S101", # use of assert — OK en tests
]
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "S105", "S106"]
"__init__.py" = ["F401"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
docstring-code-format = true
line-ending = "lf"
target-version = "py314" يتيح لـ Ruff اقتراح تحديثات تلقائية (مثل typing.List → list). per-file-ignores يسمح بالاستثناءات المُستهدفة دون تلويث الإعداد العام. docstring-code-format يُنسّق أيضًا snippets في docstrings.
الخطوة 5 — سير عمل Ruff اليومي
# Linter — affiche les violations
uv run ruff check .
# Linter avec auto-fix
uv run ruff check . --fix
# Linter avec fix unsafe
uv run ruff check . --fix --unsafe-fixes
# Formatter
uv run ruff format .
# Check sans modifier (CI)
uv run ruff format --check .
# Lister les règles activées
uv run ruff linter
الثلاثي العملي: ruff format ثم ruff check --fix ثم ruff check لرؤية ما يتبقّى للتصحيح يدويًا. على قاعدة كود 50,000 سطر، هذه الأوامر الثلاثة تعمل في أقل من ثانيتين إجمالًا — بعيد كل البعد عن أوقات انتظار flake8/black/isort.
الخطوة 6 — Hook pre-commit مع pre-commit framework
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.13
hooks:
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.11.14
hooks:
- id: uv-lock # vérifie que uv.lock est à jour avec pyproject.toml
# Installation
uv tool install pre-commit
pre-commit install
pre-commit run --all-files
الـ hook uv-lock يمنع مطورًا من commit تغييرات في pyproject.toml دون إعادة توليد uv.lock، مما سيُسبّب تثبيتات متباعدة بين المطوّرين. uv tool install pre-commit مكافئ لـ pipx install.
الخطوة 7 — دمج Ruff وuv في CI GitHub Actions
name: CI
on: [push, pull_request]
jobs:
qualite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v8.1.0
with:
version: "latest"
enable-cache: true
- run: uv python install 3.14
- run: uv sync --all-extras --dev
- name: Ruff lint
run: uv run ruff check .
- name: Ruff format
run: uv run ruff format --check .
- name: Tests
run: uv run pytest --cov=src --cov-report=xml
- uses: codecov/codecov-action@v6
خيار enable-cache: true في setup-uv يُخزّن مؤقتًا المُحلِّل والـ wheels المُحمَّلة. عند التشغيل الثاني، التثبيت ينخفض من 5 ثوانٍ إلى ثانية واحدة. على 100 PR شهريًا، عدة ساعات من وقت CI مُوفَّرة.
الخطوة 8 — الترحيل من Poetry / pip-tools
# Migration depuis Poetry
cp pyproject.toml pyproject.toml.poetry-backup
# Convertir [tool.poetry.dependencies] -> [project].dependencies
# et [tool.poetry.group.dev.dependencies] -> [dependency-groups.dev]
rm poetry.lock
uv lock
uv sync
uv run pytest
# Migration depuis pip-tools
cat requirements.in | xargs uv add
cat requirements-dev.in | xargs uv add --dev
للمشاريع القديمة جدًا بـ setup.py + requirements.txt، أداة migrate-to-uv تُؤتمت التحويل. للمشاريع الجديدة، البدء مباشرة بـ uv init يتجنّب كل هذا المسار.
أخطاء شائعة
| العَرَض | السبب | الحل |
|---|---|---|
| uv غير موجود بعد التثبيت | PATH غير مُحمَّل | إعادة تشغيل الطرفية أو source ~/.bashrc |
uv.lock يتغيّر على آلات أخرى |
فروقات منصات (Linux مقابل macOS) | uv يُولّد lock عالميًا افتراضيًا؛ تحقق من تطابق إصدار uv |
| Ruff يُعيد كتابة كود بعد formatter | تعارض قواعد linter مع formatter | تعطيل E501 (طول السطر، يُدار من formatter) |
| قاعدة S101 على الاختبارات | per-file-ignores مفقود | إضافة "tests/**/*.py" = ["S101"] |
| Import غير مستخدم في __init__.py | F401 صارم جدًا لإعادات التصدير | per-file-ignores ["F401"] على __init__.py |
| الاختبارات لا تجد الحزمة | package = true مفقود |
إضافة package = true في [tool.uv] |
الأسئلة الشائعة
uv أم Poetry في 2026؟
uv لكل مشروع جديد: أسرع 10-50×، يتبع PEPs قياسية، مستقبل مضمون. Poetry يبقى قابلًا للاستخدام للمشاريع الموجودة حيث الترحيل ليس أولوية.
Ruff أم black + isort + flake8؟
Ruff منهجيًا: ثنائي واحد، أسرع 100×، إعداد موحّد. Black يبقى لقيود استقرار طويل الأمد، لكن Ruff format متوافق مع Black.
كيف ننتقل لـ Ruff تدريجيًا على قاعدة موجودة؟
تفعيل مجموعة فرعية من القواعد، ruff check --fix، commit، ثم توسيع select تدريجيًا. تجنّب ruff check --add-noqa الذي يُلوّث الكود بتعليقات.
هل uv يدعم wheels الخاصة؟
نعم عبر [[tool.uv.index]] بـ URL وcredentials عبر متغيّر بيئة. متوافق مع Azure Artifacts وAWS CodeArtifact وJFrog.
هل نحفظ .venv؟
لا. أضف .venv/ إلى .gitignore. uv يُعيد إنشاء البيئة في ثوانٍ من lock.