9. عمليات الاستيراد
الخطأ الذي واجهناه في الإصدار 1 من تمرين التطبيق يدفعنا إلى استكشاف دور عبارة [import] بمزيد من التعمق.

9.1. البرامج النصية [import_01]
سيتم استيراد البرنامج النصي [imported] بواسطة برامج نصية مختلفة (تسمى أيضًا وحدات):

يتم تنفيذ الوحدة النمطية عند استيرادها. لذا، عند استيراد الوحدة النمطية [المستوردة]:
- سيظهر ناتج السطر 3؛
- سيتم تعيين قيمة للمتغير x في السطر 5؛
النص البرمجي [main_01] هو كما يلي:
- السطر 2: يتم استيراد الوحدة النمطية [imported]. سيؤدي ذلك إلى تنفيذها:
- سيتم عرض القيمة 2؛
- يتم إنشاء المتغير x بالقيمة 4؛
- السطر 4: يتم استخدام المتغير x من الوحدة المستوردة؛
في PyCharm، يتم الإبلاغ عن خطأ:
في [1]، يشير PyCharm إلى أنه لا يتعرف على الوحدة النمطية [imported]. من الناحية الفنية، هذا يعني أن المجلد الذي يحتوي على الوحدة النمطية [imported] غير موجود في مسار Python في PyCharm. مسار Python هو مجموعة المجلدات التي يتم البحث فيها عن الوحدات النمطية المستوردة. لحل هذه المشكلة، ما عليك سوى تعيين المجلد الذي يحتوي على الوحدة النمطية [المستوردة] كمجلد [Root Sources]، وهو في هذه الحالة المجلد [import/01]:


بعد هذه الخطوة، تتم إضافة المجلد [import/01] إلى مسار Python في PyCharm ويختفي الخطأ:

- في [1]، تغير لون المجلد [01]؛
- في [2-3]، لم يعد هناك خطأ؛
نتائج التنفيذ هي كما يلي:
تعليقات
- السطر 2 هو نتيجة تنفيذ الوحدة المستوردة؛
- السطر 3 يعرض قيمة المتغير x من الوحدة المستوردة؛
النقطة الأساسية المستفادة من هذا المثال هي المفهوم المهم المتمثل في أن الوحدة النمطية (أو البرنامج النصي) المستوردة يتم تنفيذها.
النص البرمجي [main_02] هو كما يلي:
- يستخدم السطر 2 صيغة استيراد مختلفة [from module import object1, object2, …]. هنا، نستورد المتغير [imported.x]. باستخدام هذه الصيغة، يصبح المتغير x متغيرًا في البرنامج النصي [main_02]. لم نعد بحاجة إلى إرفاق اسم الوحدة النمطية [imported] به؛
- السطر 4: نطبع المتغير x من [main_02]؛
نتائج التنفيذ هي كما يلي:
النص البرمجي [main_03] هو كما يلي:
تعني صيغة [import *] في السطر 2 أننا نستورد جميع الكائنات المرئية من الوحدة المستوردة (المتغيرات، الدوال).
والنتائج هي كما يلي:
النص البرمجي [main_04] هو كما يلي:
يُظهر السطر 3 أنه يمكننا استيراد كائن من الوحدة المستوردة وإعطائه اسمًا مستعارًا. هنا، تصبح المتغير [imported.x] المتغير [main_04.y]. النتائج هي نفسها كما في السابق.
9.2. النص البرمجي [import_02]

الوحدة المستوردة [module1.py] هي كما يلي:
تُعرّف الوحدة المستوردة دالة، وهو سيناريو شائع.
النص البرمجي [main_01] هو كما يلي:
- السطر 2: يتم استيراد الوحدة النمطية. سيتم تنفيذها. هنا، لا يتم عرض أي شيء؛
- السطر 4: يتم تنفيذ الدالة [f1] من الوحدة المستوردة؛
نتائج التنفيذ هي كما يلي:
ملاحظة: لمنع PyCharm من الإبلاغ عن خطأ في الاستيراد في السطر 2، يجب وضع المجلد الذي يحتوي على [module1] في [Root Directories] في PyCharm:

في [1]، يتحول لون المجلد [02] الموجود في دليل [Root Sources] إلى اللون الأزرق. لاحظ أن الخطأ المبلغ عنه لا يمنع البرامج النصية من العمل بشكل صحيح هنا. في الواقع، عند تنفيذ البرنامج النصي [main_0x]، تتم إضافة مجلد البرنامج النصي تلقائيًا إلى مسار Python. ونتيجة لذلك، يتم العثور على [module1]. من الآن فصاعدًا، عندما يظهر مجلد باللون الأزرق في لقطة شاشة، فهذا يعني أنه تم وضعه في [Root Sources] في PyCharm.
النص البرمجي [main_02] هو كما يلي:
- يستورد السطر 2 الدالة [f1] من الوحدة النمطية [module1]؛
- في السطر 4، يتم استخدام الدالة f1؛
النتائج مطابقة لتلك الخاصة بالنص البرمجي [main_01].
9.3. البرامج النصية [import_03]

ملاحظة: [03] موجود في [Root Sources] للمشروع.
ستقوم البرامج النصية الجديدة باستيراد الوحدة النمطية [module2]، التي لا توجد في نفس المجلد الذي توجد فيه.
النص البرمجي [module2] هو كما يلي:
وبالتالي، فإن البرنامج النصي يُعرّف دالة [f2].
النص البرمجي [main_01] هو كما يلي:
- السطر 2: نستخدم ترميزًا خاصًا للإشارة إلى كيفية العثور على الوحدة النمطية [module2]. يجب قراءة [dir1.module2] على أنها المسار [dir1/module2]: للعثور على [module2]، ابدأ من مجلد البرنامج النصي الحالي [main_01]، ثم انتقل إلى [dir1]، وستجد هناك [module2]. ضع في اعتبارك أن نقطة البداية للمسار هي مجلد البرنامج النصي الذي يقوم بالاستيراد؛
- السطر 4: لتنفيذ الدالة [f2] من [module2]؛
والنتائج هي كما يلي:
السطر 2، نتيجة دالة [f2].
النص البرمجي [main_02] هو كما يلي:
في السطر 2، نقوم بإعادة تسمية الوحدة النمطية [dir1.module] لتبسيط الكود في السطر 4.
النص البرمجي [main_03] هو كما يلي:
هذه المرة، في السطر 2، نقوم باستيراد الدالة [f2] فقط، والتي تصبح بعد ذلك دالة في البرنامج النصي [main_03] (السطر 4).
تعمل جميع هذه البرامج النصية في بيئة PyCharm بنفس الكفاءة التي تعمل بها في وحدة تحكم Python. والسبب هو أن دليل البرنامج النصي الذي يتم تنفيذه —وهو هنا الدليل [03]— هو جزء من مسار Python في كلتا الحالتين. ونتيجة لذلك، يتم العثور على الدليل [dir1/module2].
9.4. البرامج النصية [import_04]

هنا، تم وضع المجلدين [dir1] و [dir2] في [Root Sources] لمشروع PyCharm.
الوحدة النمطية الأولى التي تم استيرادها هي [module3]:
الوحدة الثانية التي تم استيرادها هي [module4]:
- السطر 1: نستورد الدالة [f3] من [module3]. وهنا، يكون [module3] مرئيًا لأننا وضعنا دليله [dir1] في [Root Sources]؛
- الأسطر 4–6: نُعرّف دالة [f4] تستدعي الدالة [f3] من [module3]؛
النص البرمجي الرئيسي [main_01] هو كما يلي:
- السطر 2: استيراد الوحدة النمطية [module4]. هذا مرئي لأننا وضعنا دليلها [dir2] في [Root Sources] في PyCharm؛
- السطر 4: تنفيذ الدالة [f4] من [module4]؛
فيما يلي نتائج تشغيل [main_01] في PyCharm:
الآن، دعونا نُشغّل [main_01] في محطة Python (وحدة التحكم):

النتائج هي كما يلي:
ماذا حدث؟ لا تعرف محطة Python مسار Python الخاص بـ PyCharm أو [Root Sources]. لديها مسار Python خاص بها. في هذا المسار، يوجد دائمًا مجلد البرنامج النصي الذي يتم تنفيذه، وهو في هذه الحالة البرنامج النصي [main_01]. وبالتالي فهي تعرف مجلد [import/04]. في البرنامج النصي المنفذ، تجد السطر:
from module4 import f4
يبحث مترجم Python عن [module4] في مجلدات مسار Python الخاص به. ومع ذلك، لا يوجد [module4] في [import/04]—الذي يقع بالفعل في مسار Python—ولكن في [import/04/dir2]، الذي لا يقع فيه. ومن هنا يأتي الخطأ.
إذن لدينا مشكلة واجهناها من قبل: قد يتعطل البرنامج النصي الذي يعمل بشكل صحيح في PyCharm في محطة Python. هذه مشكلة متكررة سنحتاج إلى حلها.
9.5. البرامج النصية [import_05]

ملاحظة: تمت إضافة مجلدي [dir1] و [dir2] إلى مسار Python. لاحظ أن هناك تعارضًا بالفعل هنا: سيتم العثور على [module3] و [module4] في موقعين في مسار Python في PyCharm:
- في [import/04/dir1] و [import/05/dir1] لـ [module3]؛
- في [import/04/dir2] و[import/05/dir2] لـ [module4]؛
يمكننا بعد ذلك إزالة [import/04/dir1] و [import/04/dir2] من [Root Sources] لمشروع PyCharm. اتضح أن [import/05/dir1] هنا هو نسخة من [import/04/dir1] (وينطبق الأمر نفسه على [dir2])، لذا لا توجد مشكلة. ومع ذلك، تجدر الإشارة إلى أنه داخل PyCharm نفسه، يجب الانتباه إلى قائمة المجلدات في [Root Sources] لتجنب التعارضات.
يصبح البرنامج النصي [main_01] كما يلي:
نحن نحاول حل مشكلة مسار Python. نريد مسارًا يعمل في PyCharm بنفس الكفاءة التي يعمل بها في محطة Python. للقيام بذلك، سنقوم بإعداده بأنفسنا.
- الأسطر 4–6: نضيف الدلائل [., ./dir1, ./dir2] إلى مسار Python. لكي يعمل هذا، يجب أن يكون الدليل الحالي أثناء التشغيل هو الدليل [import/05]. سيكون هذا صحيحًا في PyCharm ولكنه ليس صحيحًا بالضرورة في محطة Python، كما سنرى؛
- السطر 8: نقوم باستيراد [module4]. بناءً على ما قمنا به للتو، يجب العثور عليه في [./dir2]؛
يؤدي التنفيذ في PyCharm إلى النتائج التالية:
الآن، في محطة Python:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>python main_01.py
f3
f4
السطر 1، دليل التنفيذ هو [import/05].
الآن دعونا نرتقي مستوى واحدًا في شجرة الدلائل من [import/05]:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>cd ..
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_01.py
Traceback (most recent call last):
File "05/main_01.py", line 8, in <module>
from module4 import f4
ModuleNotFoundError: No module named 'module4'
- السطر 2: عند تنفيذ [main_01]، لم نعد في المجلد [import/05] بل في [import]. ومع ذلك، كتبنا:
sys.path.append(".")
sys.path.append("./dir1")
sys.path.append("./dir2")
يؤدي هذا إلى إضافة المجلدات [import، import/dir1، import/dir2] إلى مسار Python، وهو ما لا نريده على الإطلاق. لاحظ أن إضافة مجلدات غير موجودة (import/dir1، import/dir2) إلى مسار Python لا تسبب أخطاء.
لقد أحرزنا تقدمًا، لكن هذا لا يكفي. نحتاج إلى إضافة مسارات مطلقة إلى مسار Python، وليس مسارات نسبية.
البرنامج النصي [main_02] هو نسخة معدلة من [main_01] تستخدم ملف تكوين [config.json]:
{
"dependencies": [
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir1",
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir2"
]
}
قيمة مفتاح [dependencies] هي قائمة الدلائل التي سيتم إضافتها إلى مسار Python. لاحظ أننا استخدمنا هنا مسارات مطلقة بدلاً من مسارات نسبية.
يستخدم البرنامج النصي [main_02] ملف [config.json] على النحو التالي:
- السطر 6: لاحظ أننا استخدمنا المسار المطلق لملف التكوين؛
- السطران 8-9: يتم قراءة ملف التكوين. يتم إنشاء قاموس [config] (السطر 9) من محتوياته؛
- الأسطر 11-13: تتم إضافة عناصر المصفوفة [config['dependencies']] إلى مسار Python. لاحظ أنه نظرًا لاستخدامنا أسماء مجلدات مطلقة في [config.json]، فإننا نضيف أسماء مطلقة إلى مسار Python؛
- السطر 16: يتم استيراد [module4]. يجب العثور عليه لأن [dir2] موجود الآن في مسار Python؛
يؤدي التنفيذ إلى نفس النتائج التي تم الحصول عليها في [main_02]، باستثناء أن البرنامج النصي يستمر في العمل حتى عندما لا يكون دليل التنفيذ هو [import/05] بعد الآن:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_02.py
f3
f4
السطر 1، دليل التنفيذ هو [import].
لقد أحرزنا تقدماً. لقد رأينا:
- أنه كان علينا إنشاء مسار Python بأنفسنا؛
- أنه كان علينا تضمين المسارات المطلقة لجميع المجلدات التي تحتوي على الوحدات النمطية التي يستوردها التطبيق؛
ومع ذلك، فإن وضع المسارات المطلقة في البرامج النصية ليس حلاً. فبمجرد نقل المشروع إلى موقع آخر، يتوقف عن العمل. نحتاج إلى إيجاد طريقة أخرى.
9.6. البرامج النصية [import_06]

ملاحظة: تم وضع المجلدات [06، dir1، dir2] في [Root Sources] لمشروع PyCharm. المجلدان [dir1، dir2] مطابقان لتلك الموجودة في الأمثلة السابقة.
ملف [config.json] هو كما يلي:
{
"rootDir": "C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06",
"relativeDependencies": [
"dir1",
"dir2"
],
"absoluteDependencies": [
]
}
نقدم نوعين من المسارات:
- المسارات المطلقة، الأسطر 7–8؛
- المسارات النسبية، الأسطر 3–6. هذه المسارات نسبية بالنسبة إلى الجذر الموجود في السطر 2. وبالتالي، عندما ينتقل المشروع إلى موقع جديد، لا يلزم تعديل سوى هذا السطر؛
يستخدم البرنامج النصي [utils.py] ملف [config.json] ويبني مسار Python:
- السطر 8: تستقبل الدالة [config_app] اسم ملف التكوين كمعلمة؛
- الأسطر 12–14: يُستخدم ملف التكوين لإنشاء قاموس [config]؛
- السطر 20: [sys.path] هي قائمة الدلائل الموجودة في مسار Python؛
- الأسطر 17–20: تُضاف التبعيات النسبية من ملف التكوين إلى مسار Python. تُضاف إلى بداية قائمة [sys.path]، السطر 20. وذلك لأن Python، عند البحث عن وحدة نمطية، يستكشف الدلائل الموجودة في [sys.path] بالترتيب. ومع ذلك، في هذا المستند، ستوجد الوحدات النمطية التي تحمل الأسماء نفسها في دلائل مختلفة داخل [sys.path]. من خلال وضع تبعيات التطبيق في بداية مصفوفة [sys.path]، نضمن البحث عنها قبل الدلائل الأخرى في [sys.path] التي قد تحتوي على وحدات نمطية تحمل الأسماء نفسها؛
- الأسطر 21–24: تتم إضافة التبعيات المطلقة لملف التكوين إلى مسار Python؛
- السطر 26: يتم إرجاع تكوين التطبيق؛
- السطران 29 و30: تُرجع الدالة [get_scriptdir] المسار المطلق للدليل الذي يحتوي على البرنامج النصي قيد التشغيل حاليًا (الدليل الذي يوجد فيه استدعاء الدالة)؛
النص البرمجي الرئيسي [main] هو كما يلي:
- السطر 4: يتم استيراد الدالة [config_app]. لاحظ أنه نظرًا لوجود [utils] و [main] في نفس الدليل، فإن هذا [import] يعمل دائمًا. وذلك لأن دليل البرنامج النصي الرئيسي يُضاف تلقائيًا إلى مسار Python؛
- الأسطر 7–12: تعرض الدالة [display_path] قائمة المجلدات الموجودة في مسار Python؛
- السطر 19: يتم تكوين التطبيق. لاحظ أن المسار المطلق لملف التكوين يتم تمريره إلى دالة [config_app]. بعد هذا البيان، يتم إعادة بناء مسار Python؛
- السطر 22: نقوم باستيراد [module4]. وبفضل إعادة بناء مسار Python، سيتم العثور على هذه الوحدة النمطية؛
- السطر 24: يتم تنفيذ الدالة [f4]؛
في بيئة PyCharm، تكون نتائج التنفيذ كما يلي:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
…
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
….
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
Process finished with exit code 0
تعليقات
- الأسطر 2–13: مسار Python في PyCharm. ويشمل جميع المجلدات الموجودة في [Root Sources] بالمشروع؛
- الأسطر 14–29: مسار Python الذي تم إنشاؤه بواسطة الدالة [config_app]. تحتوي الأسطر 15–16 على التبعيتين اللتين أضفناهما؛
- الأسطر 22–27: الدلائل النظامية لمترجم Python الذي نفذ البرنامج النصي؛
- الأسطر 28–29: يستمر التنفيذ بشكل طبيعي؛
الآن، لنعد إلى السياق الذي تسبب سابقًا في حدوث خطأ في وقت التشغيل:
- افتح محطة Python؛
- انتقل إلى دليل آخر غير الذي يحتوي على البرنامج النصي الذي تم تنفيذه؛
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
هذه المرة يعمل (السطران 20–21). لاحظ أن [sys.path] لا يحتوي على نفس الدلائل كما هو الحال عند التشغيل في PyCharm.
9.7. البرامج النصية [import_07]
نقوم بتحسين الحل السابق بطريقتين:
- نستبدل ملف التكوين [config.json] بنص برمجي [config.py]. في الواقع، يمثل ملف JSON مشكلة كبيرة: لا يمكن إضافة تعليقات عليه. يمكن استبدال قاموس [config.json] بقاموس Python، الذي يتميز بإمكانية إضافة التعليقات عليه؛
- نستخدم وحدة نمطية مرئية لجميع مشاريع Python على الجهاز؛
9.7.1. تثبيت وحدة على مستوى الجهاز

أعلاه، نقوم بإنشاء مجلد [packages/myutils] في مشروع PyCharm (الأسماء لا تهم).
النص البرمجي [myutils.py] هو كما يلي:
- الأسطر 6–18: تقوم الدالة [set_syspath] بإنشاء مسار Python Path باستخدام قائمة الدلائل التي تم تمريرها إليها كمعلمة؛
- الأسطر 12–15: نتحقق من وجود الدليل المراد إضافته إلى مسار Python؛
فيما يلي نص البرنامج النصي [__init.py__] (يجب أن يسبق الاسم ويليه شرطان سفليان؛ وهذا أمر إلزامي):
from .myutils import set_syspath
نقوم باستيراد الدالة [set_syspath] من البرنامج النصي [myutils]. تشير التسمية [.myutils] إلى المسار [./myutils]، مما يعني أن البرنامج النصي [myutils] موجود في نفس الدليل الذي يوجد فيه [__init.py]. كان بإمكاننا استخدام الترميز [myutils]. ومع ذلك، سنقوم بإنشاء وحدة [myutils] على مستوى الجهاز. ونتيجة لذلك، سيصبح الترميز [from myutils import set_syspath] غامضًا. هل يشير إلى استيراد البرنامج النصي [myutils] من الدليل الحالي أم البرنامج النصي [myutils] على مستوى الجهاز؟ يحل الترميز [.myutils] هذا الغموض.
النص البرمجي [setup.py] (هنا أيضًا، الاسم ثابت) هو كما يلي:
from setuptools import setup
setup(name='myutils',
version='0.1',
description='Utilitaire fixant le Python Path',
url='#',
author='st',
author_email='st@gmail.com',
license='MIT',
packages=['myutils'],
zip_safe=False)
في هذا البرنامج النصي، نصف الوحدة النمطية التي سنقوم بإنشائها. هنا، سنقوم بإنشائها محليًا. ومع ذلك، يتم استخدام نفس العملية لإنشاء وحدة نمطية موزعة رسميًا (انظر |pypi|). النقاط المهمة هنا هي كما يلي:
- السطر 3: اسم الوحدة النمطية التي يتم إنشاؤها؛
- السطر 4: إصدار الوحدة النمطية؛
- السطر 5: وصفها؛
- السطران 7-8: مؤلف الوحدة النمطية؛
لتثبيت هذه الوحدة على مستوى الجهاز، اتبع الخطوات التالية:

ثم، في محطة Python، اكتب الأمر التالي [pip install .]:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\packages>pip install .
Processing c:\data\st-2020\dev\python\cours-2020\python3-flask-2020\packages
Using legacy setup.py install for myutils, since package 'wheel' is not installed.
Installing collected packages: myutils
Attempting uninstall: myutils
Found existing installation: myutils 0.1
Uninstalling myutils-0.1:
Successfully uninstalled myutils-0.1
Running setup.py install for myutils ... done
Successfully installed myutils-0.1
من الآن فصاعدًا، يمكن لأي برنامج نصي على الجهاز استيراد وحدة [myutils] دون أن تكون موجودة في كود المشروع.
9.7.2. البرنامج النصي [config.py]

يتولى البرنامج النصي [config.py] إدارة إعدادات التطبيق:
- السطر 1: تتولى الدالة [configure] إدارة تكوين التطبيق؛
- الأسطر 7–10: القاموس الذي كان موجودًا سابقًا في [config.json]؛
- السطور 9-10: نظرًا لأننا في برنامج نصي، يمكننا الوصول مباشرةً إلى أسماء المجلدات المطلقة [dir1، dir2]؛
- الأسطر 12–14: نستخدم دالة [set_syspath] من وحدة [myutils] التي أنشأناها للتو لتعيين مسار Python للتكوين؛
- السطر 20: نُرجع قاموس تكوين التطبيق. هنا، يكون فارغًا؛
9.7.3. البرنامج النصي [main.py]
النص البرمجي الرئيسي [main] هو كما يلي:
- الأسطر 2–4: نقوم بتكوين التطبيق باستخدام الوحدة النمطية [config.py]. يمكن الوصول إليها لأنها موجودة في نفس الدليل الذي يوجد فيه البرنامج النصي الرئيسي. ومع ذلك، فإن دليل البرنامج النصي الرئيسي يكون دائمًا جزءًا من مسار Python؛
- وبحلول الوقت الذي نصل فيه إلى السطر 6، يكون مسار Python قد تم إنشاؤه ليشمل مجلد الوحدة النمطية [module4]. وبالتالي يمكننا استيرادها في السطر 7؛
- الأسطر 10–15: كل ما تبقى هو تنفيذ الدالة [f4]؛
فيما يلي نتائج التنفيذ في PyCharm:
في محطة Python خارج دليل البرنامج النصي الرئيسي، تكون النتائج كما يلي:
من الآن فصاعدًا، سنتبع دائمًا نفس الإجراء لتكوين التطبيق:
- وجود ملف نصي [config.py] في دليل البرنامج النصي الرئيسي. يحتوي هذا الملف النصي على دالة [configure] التي تخدم غرضين:
- إنشاء مسار Python للتطبيق. للقيام بذلك، يسرد [config.py] جميع المجلدات التي تحتوي على الوحدات النمطية التي يستخدمها التطبيق ويقوم بإنشاء مسار Python باستخدام مساراتها المطلقة؛
- إنشاء قاموس [config] لتكوين التطبيق؛
نطبق هذا النهج على النسخة الثانية من التمرين العملي. كما تذكرون، كانت النسخة الأولى تعمل في بيئة PyCharm ولكنها لم تعمل في محطة Python. كانت المشكلة ناجمة عن مسار Python.