إذا أصبح ملف Python واحدًا طويلًا ومزدحمًا، فالخطوة التالية ليست البحث عن مكتبة جديدة، بل تقسيم الكود إلى Modules محلية تستطيع استيرادها بين ملفات مشروعك.
في هذا الدرس من أساسيات بايثون سنركز على جانب مختلف عن شرح صيغ import العامة: ستنشئ ملفًا مثل helpers.py، تستورده من main.py، ثم تنتقل إلى Package يحتوي عدة Modules، وتفهم دور __init__.py والاستيراد النسبي، وأشهر أسباب فشل الاستيراد بين ملفات المشروع.
إذا كنت تريد أولًا تعلم import math و from ... import و as بالتفصيل، فابدأ من دليل
شرح import في Python للمبتدئين.
{alertInfo}
الفكرة الأساسية هنا: ملف .py يمكن أن يكون Module قابلًا لإعادة الاستخدام، ومجلد يحتوي Modules مترابطة يمكن تنظيمه كـ Package.
{getToc} $title={محتوى المقال}
ما الفرق بين Module وPackage في Python؟
الـ Module هو ملف Python واحد، مثل helpers.py أو calculator.py. أما الـ Package فهو مجلد يجمع Modules مرتبطة ببعضها داخل مساحة أسماء واحدة.
| العنصر | شكله | متى تستخدمه؟ |
|---|---|---|
| Module | helpers.py |
عندما تريد نقل دوال أو متغيرات مترابطة إلى ملف مستقل. |
| Package | tools/ |
عندما يصبح لديك أكثر من Module مرتبطة وتريد تنظيمها داخل مجلد. |
إنشاء Module محلي: ملف helpers.py
ابدأ بأبسط حالة: ملفان داخل المجلد نفسه. أنشئ مجلد مشروع يحتوي:
my_project/
├── main.py
└── helpers.py
داخل helpers.py ضع دوال تريد إعادة استخدامها:
def format_name(name):
return name.strip().title()
def is_valid_age(age):
return age >= 0
الآن أصبح helpers.py Module محليًا يحتوي منطقًا يمكن استخدامه من ملفات أخرى بدل تكراره.
استيراد ملف Python من ملف آخر في نفس المجلد
داخل main.py يمكنك استيراد الملف كاملًا بدون كتابة الامتداد .py:
import helpers
name = helpers.format_name(" ali saleh ")
print(name)
الناتج:
Ali Saleh
ويمكنك استيراد دالة محددة فقط:
from helpers import format_name
print(format_name(" sara ahmed "))
{alertSuccess} عند استيراد ملف محلي من المجلد نفسه، اكتب اسم الملف بدون.py: استخدمimport helpersوليسimport helpers.py.
مراجعة سريعة: import وfrom import وas
هذه الصفحة لا تعيد شرح صيغ import من البداية، لكنك ستراها أثناء تنظيم الملفات المحلية:
| الصيغة | مثال محلي | النتيجة |
|---|---|---|
import module |
import helpers |
تستخدم helpers.function(). |
from module import name |
from helpers import format_name |
تستخدم الدالة مباشرة. |
import module as alias |
import helpers as h |
اسم محلي أقصر عند الحاجة. |
للتفصيل في المكتبات الجاهزة مثل math وrandom وصيغ الاستيراد المختلفة، استخدم دليل import المرجعي بدل توسيع هذا الدرس في نفس النية.
متى أنقل الكود إلى Module مستقل؟
لا تقسّم المشروع إلى ملفات كثيرة لمجرد التقسيم. أنشئ Module عندما يصبح لديك جزء من الكود له مسؤولية واضحة ويمكن إعادة استخدامه.
helpers.pyلدوال مساعدة عامة.validation.pyللتحقق من المدخلات.reports.pyلإنشاء التقارير.storage.pyللقراءة والكتابة المرتبطة بالبيانات.
إذا كان هدفك هو تعلم هيكل المشروع كاملًا مثل README وrequirements.txt وتقسيم المجلدات على مستوى أوسع، راجع مقال
تنظيم ملفات مشروع Python بعد الأساسيات.
إنشاء Package في Python
عندما تزيد Modules المرتبطة ببعضها، يمكن جمعها داخل Package. مثال:
my_project/
├── main.py
└── tools/
├── __init__.py
├── text.py
└── numbers.py
في هذا المثال، المجلد tools هو Package، والملفان text.py وnumbers.py هما Modules داخله.
داخل tools/text.py:
def clean_text(text):
return text.strip().lower()
وفي main.py:
from tools.text import clean_text
value = clean_text(" PYTHON ")
print(value)
الناتج:
python
ما وظيفة __init__.py؟
للمبتدئ، أفضل طريقة لإنشاء Package عادية وواضحة هي وضع ملف باسم __init__.py داخل المجلد. يمكن أن يكون الملف فارغًا تمامًا.
tools/
├── __init__.py
├── text.py
└── numbers.py
وجود __init__.py يجعل نية المجلد واضحة كـPackage عادية، ويمكن أيضًا وضع كود تهيئة أو إعادة تصدير أسماء داخله عند الحاجة. في Python الحديثة توجد أيضًا namespace packages قد تعمل بدون هذا الملف، لكنها حالة أكثر تقدمًا ولا نحتاجها هنا.
مثلًا، يمكن أن يحتوي tools/__init__.py على:
from .text import clean_text
ثم يصبح الاستيراد من خارج الحزمة:
from tools import clean_text
print(clean_text(" Report "))
الاستيراد النسبي Relative Import داخل Package
إذا كان Module داخل Package يحتاج Module آخر من الحزمة نفسها، يمكن استخدام نقطة في بداية المسار.
لنفترض أن لدينا:
tools/
├── __init__.py
├── text.py
└── reports.py
داخل tools/reports.py يمكن استيراد clean_text من الملف المجاور:
from .text import clean_text
def build_title(title):
return clean_text(title).title()
النقطة . تعني: ابدأ من الـPackage الحالية. أما .. فتعني الرجوع إلى الـPackage الأب.
{alertWarning} الاستيراد النسبي يعتمد على سياق الـPackage. إذا شغّلت ملفًا داخليًا مباشرة مثلpython tools/reports.pyفقد يظهرImportError: attempted relative import with no known parent package. شغّل نقطة الدخول من جذر المشروع أو شغّل الـModule باستخدامpython -mعند الحاجة.
مثال: تشغيل Module داخل Package باستخدام -m
إذا كان لديك هذا الهيكل:
my_project/
└── tools/
├── __init__.py
├── text.py
└── reports.py
ومن داخل reports.py تستخدم relative import، انتقل في Terminal إلى my_project ثم شغّل:
python -m tools.reports
بهذه الطريقة تعرف Python أن reports جزء من Package اسمها tools.
ماذا عن if __name__ == "__main__"؟
هذه العبارة مفيدة عندما يحتوي Module على دوال قابلة للاستيراد، لكن لديك أيضًا كود تريد تشغيله فقط عند تنفيذ الملف مباشرة.
def greet(name):
return f"Hello {name}"
if __name__ == "__main__":
print(greet("Ali"))
عند استيراد الملف، يتم تعريف greet() لكن الكود داخل الشرط لا يعمل تلقائيًا. ولأن هذا الموضوع له نية مستقلة وشرح أعمق، راجع مقال
ما معنى if __name__ == "__main__" في Python؟.
لماذا يظهر ModuleNotFoundError مع ملف محلي؟
إذا كان الاستيراد لملف من مشروعك، فلا تبدأ مباشرة بـpip install. افحص أولًا مكان الملف وطريقة تشغيل المشروع.
| المشكلة | مثال | ما الذي تراجعه؟ |
|---|---|---|
| الملف غير موجود في المسار المتوقع | import helpers |
تأكد أن helpers.py موجود في مكان يمكن لبايثون الوصول إليه. |
| تشغيل ملف داخلي من مجلد فرعي | python tools/reports.py |
شغّل من جذر المشروع أو استخدم python -m tools.reports. |
| اسم ملف يتعارض مع مكتبة | random.py |
غيّر اسم الملف ولا تستخدم أسماء المكتبات القياسية لملفات مشروعك. |
| relative import خارج سياق Package | from .text import clean_text |
لا تشغّل Module الداخلية مباشرة كنقطة دخول مستقلة. |
| المشكلة في مكتبة خارجية | import requests |
هنا افحص التثبيت والبيئة باستخدام دليل الخطأ المتخصص. |
إذا كانت المشكلة مع مكتبة خارجية أو بيئة Python نفسها، راجع حل خطأ ModuleNotFoundError: No module named.
هل أستخدم sys.path.append لحل مشكلة الاستيراد؟
يمكن تعديل sys.path يدويًا، لكن لا تجعله الحل الأول في مشروع مبتدئ. في معظم الحالات الأفضل أن تنظّم Modules داخل مشروع واضح، وتشغّل البرنامج من جذر المشروع، وتستخدم imports مناسبة للـPackage.
إضافة مسارات يدويًا قد تخفي مشكلة في بنية المشروع وتجعل تشغيل الكود يعتمد على مسارات خاصة بجهاز واحد.
مثال كامل: من ملف واحد إلى Package صغيرة
لنفترض أن مشروعك بدأ بملف واحد ثم أصبح لديك منطق للنصوص والأرقام. الهيكل:
my_project/
├── main.py
└── tools/
├── __init__.py
├── text.py
└── numbers.py
داخل tools/text.py:
def normalize_name(name):
return name.strip().title()
داخل tools/numbers.py:
def is_positive(number):
return number > 0
داخل main.py:
from tools.text import normalize_name
from tools.numbers import is_positive
name = normalize_name(" ahmed ali ")
score = 25
print(name)
print(is_positive(score))
الناتج:
Ahmed Ali
True
الآن كل ملف له مسؤولية واضحة، وmain.py أصبح نقطة تشغيل تجمع الأدوات بدل احتواء كل التفاصيل.
أفضل ممارسات Modules وPackages للمبتدئ
- ابدأ بملفات قليلة، ولا تقسّم المشروع أكثر من حاجته.
- اختر أسماء ملفات تصف مسؤوليتها مثل
validation.pyبدلfile2.py. - لا تسمِّ ملفاتك
random.pyأوjson.pyأوdatetime.pyإذا كنت تحتاج المكتبات الأصلية نفسها. - شغّل المشروع من مجلده الجذر عندما تبدأ باستخدام Packages.
- استخدم absolute imports بين نقطة الدخول والحزم عندما يكون ذلك أوضح.
- استخدم relative imports داخل الحزمة عندما تكون العلاقة داخلية وواضحة.
- لا تستخدم
sys.path.append()كحل تلقائي لكل خطأ استيراد.
أسئلة شائعة
هل أي ملف .py يعتبر Module في Python؟
نعم، ملف Python يمكن استيراده كـModule عندما يكون موجودًا في مسار يستطيع نظام الاستيراد الوصول إليه.
كيف أستورد ملف Python من ملف آخر في نفس المجلد؟
إذا كان لديك helpers.py بجانب main.py، استخدم import helpers أو from helpers import function_name بدون كتابة .py.
ما الفرق بين Module وPackage؟
Module هو ملف Python واحد. Package تجمع Modules داخل مجلد ويمكن الوصول إلى Modules داخلها باستخدام أسماء منقطة مثل tools.text.
هل __init__.py إلزامي دائمًا؟
ليس في كل الحالات الحديثة بسبب namespace packages، لكن إضافته هي الطريقة الأبسط والأوضح للمبتدئ لإنشاء Package عادية، ويمكن أن يبقى فارغًا.
لماذا يفشل relative import عندما أشغل الملف مباشرة؟
لأن relative import يعتمد على معرفة الـPackage التي ينتمي إليها الملف. عند تشغيل Module داخلية مباشرة قد تفقد هذا السياق؛ شغّل نقطة الدخول من جذر المشروع أو استخدم python -m package.module.
مصادر رسمية للتوسع
- Python Documentation — Modules and Packages
- Python Documentation — The import system
- Python Documentation — __main__
الخلاصة
بعد فهم أساسيات import، الخطوة العملية هي استخدامه لتنظيم كودك أنت. أنشئ Module مثل helpers.py عندما تريد إعادة استخدام مجموعة دوال، ثم اجمع Modules المرتبطة داخل Package مثل tools عندما يكبر المشروع.
ركز أولًا على الاستيراد بين ملفات المشروع، وافهم __init__.py وrelative imports ومكان تشغيل البرنامج. بهذه الطريقة تتجنب كثيرًا من مشاكل ModuleNotFoundError وتنتقل من ملف واحد مزدحم إلى مشروع أوضح وأسهل في التطوير.
{alertSuccess} القاعدة العملية: ابدأ بـModule عندما تحتاج ملفًا مستقلًا لمسؤولية واضحة، وانتقل إلى Package عندما يصبح لديك عدة Modules مرتبطة ببعضها.




