إذا أظهر ملف بايثون داخل حزمة الخطأ ImportError: attempted relative import with no known parent package عند تشغيله مباشرةً، فابدأ بتشغيله كوحدة نمطية (module) من المجلد الموجود أعلى الحزمة مباشرةً. في نظام macOS، انتقل إلى المجلد الجذري للمشروع في تطبيق Terminal، ثم شغّل الأمر python3 -m package.module. يمنح هذا الإجراء لغة بايثون سياق الحزمة الذي لا يوفره مسار الملف المباشر.

لماذا يتعطل الاستيراد النسبي عند تشغيل ملف مباشرةً؟

يعتمد الاستيراد النسبي مثل from .helpers import format_result على اسم حزمة الوحدة النمطية. تستخدم بايثون النقاط البادئة لتحديد الحزمة الحالية والحزم الأصلية لها. عندما تشغّل ملفًا باستخدام python3 path/to/file.py، تقوم بايثون بتشغيل هذا الملف باعتباره وحدة __main__ من المستوى الأعلى؛ ولا تمنحه البيانات الوصفية الخاصة بالحزمة والمطلوبة لحل النقطة وفهمها. وبالتالي، يمكن أن يفشل الاستيراد حتى وإن كان helpers.py موجودًا بجوار الملف تمامًا. يشرح مرجع الاستيراد في بايثون عمليات الاستيراد النسبي والتعامل الخاص مع __main__.

على سبيل المثال، لنفترض أن مشروعك منظم على النحو التالي:

project/
└── myapp/
    ├── __init__.py
    ├── cli.py
    └── helpers.py

إذا كان cli.py يحتوي على from .helpers import format_result، فإن تشغيل python3 myapp/cli.py من داخل مجلد project هو استدعاء خاطئ. تكمن المشكلة في الطريقة التي طُلب بها من بايثون تشغيل الملف، وليس بالضرورة في وجود خطأ في الاستيراد النسبي أو موقع الملف نفسه.

تشغيل الوحدة النمطية من المجلد الجذري للمشروع على macOS

افتح تطبيق Terminal وانتقل إلى المجلد الذي يحتوي على myapp. استبدل مسار المثال بالموقع الفعلي لمشروعك. ضع المسار بين علامتي اقتباس حتى يتعامل غلاف الأوامر (shell) مع المسافات بشكل صحيح؛ علمًا بأن الغلاف الافتراضي في Terminal على macOS هو zsh. يوضح دليل Terminal من Apple هذا الإعداد الافتراضي.

cd "/Users/yourname/Projects/project"
python3 -m myapp.cli

يطلب الخيار -m من بايثون البحث عن الوحدة النمطية وتشغيلها باستخدام اسمها النقطي المنسوب للحزمة. احتفظ باسم الحزمة في الأمر واحذف امتداد .py والشرطات المائلة الخاصة بنظام الملفات. يبدأ مسار بحث الوحدات النمطية في بايثون من الدليل الحالي عند الاستدعاء باستخدام -m، ولهذا السبب يعد التشغيل من المجلد الجذري للمشروع أمرًا ضروريًا. توضح وثائق sys.path في بايثون مسار البداية هذا.

إذا كان الأمر يستخدم إصدارًا خاطئًا من بايثون، فقم بتنشيط البيئة الافتراضية الحالية للمشروع أولاً، ثم استخدم نفس نمط python -m. بالنسبة لمجلد بيئة افتراضية نمطي باسم .venv في المجلد الجذري للمشروع:

cd "/Users/yourname/Projects/project"
source .venv/bin/activate
python -m myapp.cli

يؤدي استخدام python بعد التنشيط إلى تحديد المترجم الفوري (interpreter) الخاص بالبيئة الافتراضية. إذا كانت بيئتك تحمل اسمًا مختلفًا أو تقع في مسار آخر، فعدّل مسار التنشيط بناءً على ذلك؛ ولا تفترض دائمًا وجود مجلد باسم .venv. يمكنك التحقق من المترجم المحدد عبر الأمر python -c 'import sys; print(sys.executable)'.

إذا كنت تريد تشغيل الحزمة نفسها

بالنسبة للأمر المخصص لتشغيل الحزمة بالكامل، أضف ملف __main__.py داخل الحزمة واجعل نقطة الإدخال فيه موجزة ومقتضبة:

myapp/
├── __init__.py
├── __main__.py
├── cli.py
└── helpers.py

في ملف myapp/__main__.py، استورد الدالة الرئيسية للحزمة وقم باستدعائها. بعد ذلك، شغّل الأمر python3 -m myapp من المجلد الجذري للمشروع. تقوم بايثون بتنفيذ ملف __main__.py الخاص بالحزمة عند استخدام هذا الشكل من استدعاء -m، ويمكن لهذا الملف استخدام عمليات الاستيراد النسبي الخاصة بالحزمة. توضح وثائق __main__ في بايثون هذا النمط لنقطة إدخال الحزمة.

تحقق من هذه التفاصيل إذا استمر الخطأ

  • تأكد من دليل العمل الحالي الخاص بك. شغّل الأمر pwd في Terminal وتأكد من أنه يعرض المجلد الجذري للمشروع، وهو المجلد الذي يحتوي على myapp. وإذا كانت الحزمة متداخلة داخل مجلد مثل src، على سبيل المثال، فاستخدم اسم الحزمة القابل للاستيراد وتأكد من أن البيئة المهيأة للمشروع تتيح الوصول إليه؛ فمجرد الانتقال إلى المجلد الأصلي الخاطئ لن يحل مشكلة العثور على الوحدة النمطية.
  • استخدم اسم الحزمة الفعلي. في الأمر python3 -m myapp.cli، يجب أن يكون myapp هو اسم دليل الحزمة (أو اسم الاستيراد الخاص بها)، وأن يكون cli هو اسم ملف الوحدة النمطية بدون امتداد .py.
  • افحص سطر تتبع الخطأ (traceback). إذا تم حل الاستيراد النسبي بنجاح ولكن تعطل استيراد لاحق، فقد يرجع ذلك إلى فقدان وحدة نمطية أو مكتبة تبعية أخرى مختلفة. إن إصلاح سياق التشغيل يعالج فقط حالات الفشل المرتبطة بسياق الحزمة.
  • تجنب استخدام PYTHONPATH كحل أول. فهو يغير مسار بحث الاستيراد في بايثون، ولكنه لا يحول في حد ذاته ملفًا تم تنفيذه مباشرةً إلى وحدة نمطية تابعة لحزمة ذات تسمية صحيحة. وتحذر وثائق بايثون أيضًا من أن PYTHONPATH يمكن أن يؤثر على إصدارات وبيئات بايثون متعددة. يصف مرجع تهيئة المسار في بايثون نطاق تأثيره.
  • إذا كان التنفيذ المباشر للملف شرطًا لا بد منه، ففكر في تعديل الكود البرمجي لاستخدام استيراد مطلق مناسب وتأكد من تثبيت الحزمة أو إمكانية استيرادها بطريقة أخرى في تلك البيئة. هذا خيار إعداد مختلف؛ فلا تخلط بين استخدام استيراد نسبي لحزمة وتوقع أن يتصرف الملف مثل برنامج نصي مستقل بذاته.

القاعدة العملية هي مطابقة أمر التشغيل مع أسلوب الاستيراد: للاستيراد النسبي التابع لحزمة، شغّل الوحدة النمطية من الدليل الأصلي للحزمة باستخدام python -m. أما بالنسبة لأمر الحزمة ككل، فوفّر ملف __main__.py وشغّل الحزمة باستخدام -m.

المصادر