نشر أول حزمة بايثون على PyPI في 2026 خطوة بخطوة

حين تكتب pip install requests فأنت تسحب حزمة رفعها غيرك إلى فهرس PyPI. النشر هو الطريق المعاكس: تحزّم مكتبتك وترفعها، فيصبح بوسع أي أحد جلبها بالأمر نفسه. الخلط بين الجهتين شائع؛ يظن كثيرون أن pip install وحده يشارك كودهم، وهو في الحقيقة استهلاك من طرف واحد لا أكثر. سنقطع المسار كاملاً بهذا الترتيب: بناء الحزمة بصيغتيها القياسيتين، ثم مصادقة الحساب بطريقة 2026، ثم الرفع إلى بيئة تجريبية قبل الفهرس الحقيقي. الترتيب مقصود، وقلبه هو أكثر ما يعثّر المبتدئين.
هيكلة المشروع
يعتمد الدليل الرسمي تخطيط src/. الفكرة أن يعيش كود الحزمة في مجلد منفصل، بعيداً عن ملفات الإعداد والاختبارات، فلا يختلط ما يُبنى بما لا يُبنى. وهذه هي البنية الدنيا:
project/
├── LICENSE
├── pyproject.toml
├── README.md
├── src/
│ └── your_package/
│ └── __init__.py
└── tests/
ملف __init__.py هو ما يحوّل المجلد إلى حزمة قابلة للاستيراد، ويؤدي دوره ولو تركته فارغاً. أما README.md وLICENSE فليسا ترفاً. يعرض PyPI محتوى الـ README نصاً كاملاً في صفحة حزمتك، فإن غاب ظهرت الصفحة جرداء أو مكسورة. والترخيص الصريح يجيب سلفاً عن سؤال يطرحه كل مطوّر قبل أن يبني على كودك: بأي شروط يحق لي استعماله؟
ملف pyproject.toml
هذا هو ملف الإعداد المركزي لمشاريع بايثون الحديثة؛ يجمع نظام البناء وبيانات الحزمة في موضع واحد بدل تشتيتها. أهم قسمين فيه: [build-system] الذي يحدد الأداة التي تبني الحزمة (build-backend)، و[project] الذي يحمل الاسم والإصدار والوصف والاعتماديات. الحقلان الإلزاميان عملياً هما name وversion، وما عداهما يثري صفحة PyPI:
[build-system]
requires = ["hatchling >= 1.26"]
build-backend = "hatchling.build"
[project]
name = "example_package_YOUR_USERNAME_HERE"
version = "0.0.1"
authors = [
{ name = "Example Author", email = "[email protected]" },
]
description = "A small example package"
readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
license-files = ["LICEN[CS]E*"]
[project.urls]
Homepage = "https://github.com/pypa/sampleproject"
Issues = "https://github.com/pypa/sampleproject/issues"
اختر backend واحداً والتزم به؛ وhatchling خيار افتراضي جيد. ولتفصيل كل حقل، راجع شرح pyproject.toml: ملف واحد لإعدادات مشاريع بايثون.
بناء الحزمة
من جذر المشروع نفّذ:
python -m build
ينتج هذا ملفين داخل dist/: أرشيف مصدري بامتداد .tar.gz (sdist) يُبنى عند التثبيت، وتوزيعة مبنية جاهزة بامتداد .whl (wheel) أسرع في التثبيت لأنها لا تحتاج خطوة بناء. يُرفع الاثنان معاً. والبديل الأحدث والأسرع هو uv build، وتفاصيل الأداة في أداة uv لإدارة حزم بايثون: دليل عملي للانتقال من pip وvenv.
المصادقة في 2026
الرفع بكلمة المرور انتهى. منذ 1 يونيو 2023 مُنع الرفع بكلمة المرور لأي حساب مفعّل عليه التحقق بخطوتين، ومنذ 1 يناير 2024 صار التحقق بخطوتين إلزامياً على كل حسابات PyPI. عملياً في 2026 لم يبقَ أمامك سوى الـ API token.
أنشئ token من إعدادات حسابك على PyPI، وقيّده بمشروع واحد ما أمكن. عند الرفع يكون اسم المستخدم حرفياً __token__، وكلمة المرور هي الـ token الذي يبدأ بـ pypi-. احفظ السر في ~/.pypirc أو في متغيّرَي البيئة TWINE_USERNAME=__token__ وTWINE_PASSWORD=<token>. ولا تضعه أبداً داخل الكود أو في commit.
الرفع الآمن
افحص التوزيعات قبل رفعها لتطمئن إلى سلامة الوصف والبيانات:
twine check dist/*
ثم جرّب على TestPyPI، وهو مستودع منفصل تماماً بحساب وtoken مستقلَّين، يتيح لك التجربة دون تلويث الفهرس الحقيقي:
twine upload --repository testpypi dist/*
وحين يمرّ كل شيء، ارفع إلى PyPI:
twine upload dist/*
والبديل بأداة uv هو uv publish بعد uv build.
متى API token يدوي، ومتى Trusted Publishing؟
يعفيك النشر الموثوق من حمل سر ثابت طويل العمر. تعمل الآلية هكذا: يطلب ملف الـ workflow في GitHub Actions رمز OIDC، ويقدّمه إلى PyPI، فيردّ PyPI برمز رفع قصير العمر يُستهلك في لحظته ثم يبطل. لا يبقى هنا token دائم قد يُسرّب أو يُنسى صالحاً حتى تُبطله بيدك. الأكشن الرسمي pypa/gh-action-pypi-publish@release/v1 يطلب صلاحية id-token: write، وتُترك حقول username/password فارغة:
jobs:
pypi-publish:
name: upload release to PyPI
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
القاعدة بسيطة: للنشر المتكرر من مستودع GitHub اختر Trusted Publishing. وميزة «pending publisher» تتيح تهيئته قبل وجود المشروع على PyPI، وتُنشئ المشروع عند أول نشر ناجح. أما الرفع اليدوي العابر من جهازك فيكفيه token مقيّد بمشروع.
أخطاء شائعة تجنّبها
- محاولة الرفع بكلمة المرور بدل الـ token؛ لم يعد يعمل.
- اختيار اسم حزمة محجوز أو مكرّر؛ أسماء PyPI فريدة عالمياً.
- إعادة رفع رقم الإصدار نفسه؛ ملفات PyPI ثابتة لا تُستبدل، فارفع نسخة جديدة.
- تخطّي TestPyPI ثم اكتشاف الخطأ في الفهرس الحقيقي.
- نسيان README فيظهر الوصف مكسوراً؛ يكشفه
twine check. - تسريب الـ token في الكود أو في commit.
- الاعتماد على
python setup.py sdist uploadالمهجور.