قد يحدث خطأ الاستيراد في العديد من الحالات والسيناريوهات.
في هذه المقالة، سوف تتعلم عن خطأ استيراد يحدث عادةً أثناء التعامل مع الحزم والتبعيات في Python.
مراجعة سريعة لعبارة Import وImportError
في بايثون، تخدم عبارة Import غرضين رئيسيين:
- يتم استخدامه للبحث عن الوحدة المحددة حسب اسمها، ثم تحميلها وتشغيلها إذا كانت الوحدة مطلوبة.
- كما أنه يحدد اسمًا في مساحة الاسم المحلية ضمن نطاق عبارة الاستيراد. ومن الممكن بعد ذلك استخدام هذا الاسم المحلي للإشارة إلى الوحدة النمطية التي تم الوصول إليها في جميع أنحاء الكود.
إذا واجهت عبارة import
صعوبة في استيراد وحدة بنجاح، فإنها تثير ImportError
.
صياغة المشكلة
دعونا نحاول فهم المشكلة بشكل أفضل قبل أن ننتقل إلى الحل!
في Python، يحدث الخطأ “ImportError: cannot import name
” عادةً عندما لا يمكن الوصول إلى الفئة المستوردة، أو عندما تكون الفئة المستوردة في تبعية دائرية.
فيما يلي الأسباب الرئيسية لحدوث الخطأ "ImportError: cannot import name"
:
- الفئة المستوردة موجودة في تبعية دائرية.
- الفئة المستوردة غير متوفرة أو لم يتم إنشاؤها.
- لقد تم كتابة الفئة المستوردة بشكل خاطئ.
- تم وضع الفئة المستوردة من وحدة معينة في مكان غير صحيح.
- الفئة المستوردة غير موجودة في مكتبة Python. يحدث هذا عادةً أثناء استيراد المكتبات الخارجية.
على سبيل المثال: افترض أن لديك وحدتين: x.py
و y.py
، كما هو موضح أدناه.
تمثل هذه الملفات كيفية حدوث ImportError عندما يكون هناك اعتماد دائري بينهما، مما يؤدي إلى حالة حلقة ميتة.
دعونا نلقي نظرة على محتويات الوحدة الأولى:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from x import x_1 def y_1(): print('y1') x_1() def y_2(): print('y2') if __name__ == '__main__': y_1() |
دعونا نلقي نظرة على محتويات الوحدة الثانية:
1 2 3 4 5 6 | from y import y_2 def x_1(): print('x1') y_2() |
هل يمكنك العثور على التبعية الدائرية؟
الناتج:
1 | ImportError: cannot import name 'x_1' from partially initialized module 'x' (most likely due to a circular import) |
حدث الخطأ لأن كلا ملفي Python، أي x وy، حاولا تحميل بعضهما البعض في نفس الوقت.
حاولت وحدة y تحميل وحدة x بينما حاولت وحدة x تحميل وحدة y.
أدى هذا إلى إنشاء اعتماد تحميل دائري يؤدي إلى حدوث خطأ في ذاكرة الكومة. للتخلص من ImportError، يجب عليك التخلص من الاعتماد الدائري.
الحل 1: ببساطة استخدم Import [تجنب from X import Y]
ببساطة، تحدث المشكلة لأننا نحاول الوصول إلى محتويات وحدة واحدة من وحدة أخرى في نفس الوقت قبل أن تصبح محتويات الوحدة جاهزة/مهيئة.
يحدث هذا بشكل خاص لأنك تستخدم: from x import x_1
و from y import y_2
.
يمكن لـ Python اكتشاف التبعيات الدائرية ومنع الحلقات الميتة.
في الأساس ما يحدث هو إنشاء عنصر نائب فارغ للوحدة (أي أنه لا يحتوي على أي محتوى).
بعد تجميع الوحدات النمطية التي تعتمد على الدائرية، يقوم Python تلقائيًا بتحديث الوحدة النمطية المستوردة.
ومع ذلك، لكي يتمكن Python من حل مشكلة التبعية الدائرية، يجب عليك استخدام import x
فقط بدلاً من استيراد محتوى معين من الوحدة النمطية بمساعدة العبارة from
.
نظرًا لأنك لم تعد تحاول تحميل المحتويات الفردية للوحدة النمطية على المستوى الأعلى، يحصل Python على الوقت الكافي لتجميع الوحدة النمطية، وبالتالي التعامل مع التبعية الدائرية بنفسه.
دعونا نلقي نظرة على الكود التالي لفهم كيفية عمل ذلك:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import x def y_1(): print('y1') x.x_1() def y_2(): print('y2') if __name__ == '__main__': y_1() |
وإلى الوحدة الثانية!
1 2 3 4 5 6 | import y def x_1(): print('x1') y.y_2() |
الآن، هل يعمل هذا أم أن بايثون يثير خطأ التبعية الدائرية؟
الناتج:
1 2 3 | y1 x1 y2 |
نعم إنه يعمل!
الحل 2: إعادة ترتيب موضع عبارة Import
في المثال أعلاه، يمكنك تجنب التبعية الدائرية عن طريق إعادة تنسيق تسلسل عبارات import.
وبالتالي، بدلاً من استيراد وحدة y في البداية داخل وحدة x، يمكنك استيرادها لاحقًا، كما هو موضح في المقطع التالي:
1 2 3 4 5 6 | def x_1(): print('x1') y_2() from y import y_2 |
الناتج:
1 2 3 | y1 x1 y2 |
باختصار، يمكنك حل الخطأ “ImportError: Cannot import name X
” عن طريق حل التبعيات الدائرية.
يمكنك القيام بذلك إما عن طريق التخلص من استخدام نموذج from x import y
لاستيراد المحتويات من وحدة نمطية واستخدام عبارة import
ببساطة لاستيراد الوحدة النمطية بالكامل.
الحل الآخر لهذا الخطأ هو تغيير موضع عبارات الاستيراد وفقًا لذلك داخل الكود الخاص بك.
ليست هناك تعليقات:
إرسال تعليق