مقالات مختارة

حل خطأ FileNotFoundError في بايثون | مشكلة وحل 13

حل FileNotFoundError No such file or directory في بايثون - مشكلة وحل 13

خطأ FileNotFoundError: [Errno 2] No such file or directory يعني أن بايثون حاول الوصول إلى ملف أو مجلد ولم يجده في المسار الذي يبحث فيه. وإذا كان الملف موجودًا فعلًا، فالسبب الأكثر شيوعًا هو أن المسار النسبي مثل open("data.txt") يُفسَّر بالنسبة إلى مجلد العمل الحالي (Current Working Directory أو CWD)، وليس بالضرورة مجلد ملف .py نفسه.

ابدأ بطباعة Path.cwd() أو os.getcwd() لمعرفة أين يبحث بايثون، ثم راجع اسم الملف وامتداده. وإذا أردت أن يكون المسار ثابتًا بالنسبة إلى مكان السكربت، ابنِه من Path(__file__).resolve().parent. وفي Windows راجع أيضًا الشرطات العكسية والامتدادات المخفية.

هذا هو الدرس 13 من سلسلة مشكلة وحل في بايثون، وسنحل الخطأ خطوة بخطوة دون إخفائه بـtry/except قبل فهم السبب الحقيقي.

الخلاصة السريعة: إذا كان الملف موجودًا ومع ذلك يظهر FileNotFoundError، افحص أولًا Path.cwd() أو os.getcwd(). المسار النسبي يُحسب من CWD، لا من مكان السكربت تلقائيًا.

شكل الخطأ

قد يظهر لك الخطأ بهذا الشكل:

FileNotFoundError: [Errno 2] No such file or directory: 'data.txt'

ومعناه أن Python حاول فتح ملف اسمه data.txt لكنه لم يجد هذا الملف في المسار الحالي الذي يعمل منه البرنامج. وإذا أردت تعلم قراءة اسم الملف ورقم السطر من رسالة الخطأ، راجع شرح Traceback ورسائل الأخطاء في بايثون.

مثال كود يسبب هذا الخطأ:

with open("data.txt", "r", encoding="utf-8") as file:
    content = file.read()

print(content)

إذا لم يكن ملف data.txt موجودًا في نفس المجلد الذي يعمل منه البرنامج، ستظهر رسالة FileNotFoundError.

سبب FileNotFoundError عندما لا يجد بايثون الملف في المسار المحدد

ما معنى FileNotFoundError؟

كلمة FileNotFoundError تعني حرفيًا: خطأ بسبب أن الملف غير موجود. لكن في الواقع، السبب لا يكون دائمًا أن الملف غير موجود نهائيًا. أحيانًا يكون الملف موجودًا، لكن البرنامج يبحث عنه في مكان آخر.

مثال بسيط:

project/
│
├── main.py
└── files/
    └── data.txt

إذا كتبت داخل main.py:

open("data.txt")

قد يظهر الخطأ؛ لأن الملف ليس بجانب main.py مباشرة، بل داخل مجلد اسمه files. لذلك المسار الصحيح يكون:

open("files/data.txt")

أشهر أسباب ظهور FileNotFoundError

هناك عدة أسباب شائعة تؤدي إلى ظهور هذا الخطأ:

  • الملف غير موجود فعلًا.
  • اسم الملف مكتوب بطريقة خاطئة.
  • امتداد الملف غير صحيح، مثل كتابة data.txt بينما الملف اسمه data.csv.
  • الملف موجود لكن في مجلد مختلف.
  • تشغل البرنامج من مجلد غير الذي تتوقعه.
  • استخدام مسار يحتوي على أحرف أو شرطات غير صحيحة.
  • نسيان كتابة اسم المجلد قبل اسم الملف.
  • الاعتماد على مسار نسبي بدون معرفة المجلد الحالي.

الفرق بين المسار النسبي والمسار الكامل

لفهم هذا الخطأ جيدًا، يجب أن تفهم الفرق بين نوعين من المسارات: المسار النسبي و المسار الكامل.

المسار النسبي

المسار النسبي هو مسار يعتمد على مكان تشغيل البرنامج. مثل:

data.txt
files/data.txt
../data.txt

هذا النوع من المسارات قد يسبب ارتباكًا للمبتدئين؛ لأن Python يبحث عن الملف نسبةً إلى المجلد الحالي الذي شغلت منه البرنامج.

المسار الكامل

المسار الكامل هو المسار الذي يبدأ من جذر النظام أو القرص. مثال على Windows:

C:\Users\Elia\Desktop\data.txt

ومثال على Linux أو macOS:

/home/user/Desktop/data.txt

المسار الكامل يكون أوضح أحيانًا، لكنه أقل مرونة إذا نقلت المشروع إلى جهاز آخر.

المسار النسبي وCurrent Working Directory كسبب لخطأ FileNotFoundError

لماذا يظهر FileNotFoundError رغم أن الملف موجود؟

هذه من أكثر الحالات التي تربك المبتدئ. وجود الملف بجانب main.py لا يعني أن open("data.txt") سيبحث بجانب main.py. المسار النسبي يُفسَّر نسبةً إلى مجلد العمل الحالي CWD الذي شغلت منه البرنامج.

اطبع القيم التالية قبل سطر فتح الملف:

from pathlib import Path

print("CWD:", Path.cwd())
print("Script:", __file__)

Path.cwd() يخبرك أين تُفسَّر المسارات النسبية. أما __file__ فيشير إلى ملف السكربت نفسه عند تشغيل ملف Python عادي. إذا اختلف المكانان، فقد يكون هذا هو سبب الخطأ.

قاعدة مهمة: Path("data.txt") وopen("data.txt") كلاهما يعتمدان على CWD. مجرد استخدام pathlib لا يغيّر قاعدة المسار النسبي.

الحل الأول: تأكد أن الملف موجود فعلًا

قبل التفكير في حلول معقدة، تأكد أولًا أن الملف موجود فعلًا في المجلد الصحيح.

إذا كان الكود هكذا:

open("data.txt")

فيجب أن يكون الملف بجانب ملف Python الذي تشغله أو داخل المجلد الحالي الذي يعمل منه البرنامج.

تأكد من:

  • اسم الملف مكتوب بشكل صحيح.
  • الامتداد صحيح: .txt أو .csv أو .json، وليس امتدادًا مخفيًا مزدوجًا مثل data.txt.txt.
  • حالة الأحرف مطابقة، خصوصًا على الأنظمة الحساسة لها: Data.csv قد يختلف عن data.csv.
  • لا توجد مسافة زائدة في اسم الملف.
  • الملف ليس داخل مجلد آخر.

الحل الثاني: اكتب المسار الصحيح للملف

إذا كان الملف داخل مجلد فرعي، لا تكتب اسم الملف فقط، بل اكتب اسم المجلد معه.

مثال هيكل المشروع:

project/
│
├── main.py
└── data/
    └── users.txt

الخطأ:

open("users.txt")

الصحيح:

open("data/users.txt")

لأن الملف موجود داخل مجلد data وليس في نفس مكان ملف التشغيل.

الحل الثالث: اربط المسار بمكان السكربت باستخدام pathlib

إذا كان الملف جزءًا من مشروعك وتريد العثور عليه بغض النظر عن المجلد الذي شغلت منه البرنامج، ابنِ المسار انطلاقًا من مكان ملف Python نفسه:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent
file_path = BASE_DIR / "data" / "users.txt"

with file_path.open("r", encoding="utf-8") as file:
    content = file.read()

print(content)

أما كتابة Path("data") / "users.txt" فقط فهي طريقة جيدة لبناء المسار، لكنها تظل نسبية إلى CWD وقد تفشل إذا شغّلت البرنامج من مكان مختلف.

إذا كنت تعمل داخل بيئة تفاعلية لا توفر __file__، مثل بعض دفاتر Jupyter، فابدأ بفحص Path.cwd() وحدد نقطة أساس مناسبة لبيئتك. وللتوسع في بناء المسارات راجع شرح pathlib في بايثون.

الحل الرابع: افحص وجود الملف قبل فتحه

يمكنك فحص وجود الملف قبل محاولة فتحه، حتى تتجنب ظهور الخطأ مباشرة.

from pathlib import Path

file_path = Path("data.txt")

if file_path.exists():
    content = file_path.read_text(encoding="utf-8")
    print(content)
else:
    print("الملف غير موجود")

بهذا الشكل لن يتوقف البرنامج فجأة، بل سيعرض رسالة واضحة إذا لم يجد الملف. وللتشخيص، اطبع file_path.resolve() حتى ترى المسار الكامل الذي يحاول Python الوصول إليه.

فحص وجود الملف ومساره قبل فتحه لتشخيص FileNotFoundError في بايثون

الحل الخامس: استخدم try و except

طريقة أخرى جيدة هي استخدام try و except للتعامل مع الخطأ إذا حدث.

try:
    with open("data.txt", "r", encoding="utf-8") as file:
        content = file.read()
        print(content)

except FileNotFoundError:
    print("عذرًا، الملف غير موجود.")

هذه الطريقة مفيدة عندما يكون غياب الملف احتمالًا طبيعيًا في البرنامج، وتريد عرض رسالة مناسبة للمستخدم بدل ظهور خطأ طويل. إذا كنت تحتاج الأساس أولًا، راجع شرح try وexcept في بايثون.

مهم: استخدام try و except لا يعني تجاهل المشكلة. استخدمه لعرض رسالة واضحة أو تنفيذ بديل مناسب عند عدم وجود الملف.

الحل السادس: إذا كنت تريد إنشاء الملف استخدم وضع الكتابة

إذا كنت تريد قراءة الملف، تستخدم الوضع "r". لكن إذا كان هدفك إنشاء ملف جديد، استخدم الوضع "w".

هذا الكود يسبب خطأ إذا لم يكن الملف موجودًا:

open("notes.txt", "r")

أما هذا الكود ينشئ الملف إذا لم يكن موجودًا:

with open("notes.txt", "w", encoding="utf-8") as file:
    file.write("مرحبا من بايثون")

انتبه: الوضع "w" قد يستبدل محتوى الملف إذا كان موجودًا. إذا أردت الإضافة بدون حذف المحتوى السابق، استخدم الوضع "a". و"w" أو "a" ينشئان الملف عند غيابه، لكنهما لا ينشئان مجلدًا أبًا غير موجود؛ أنشئ المجلد أولًا مثل Path("output").mkdir(parents=True, exist_ok=True).

وضع الفتح المعنى ماذا يحدث إذا لم يكن الملف موجودًا؟
"r" قراءة يظهر FileNotFoundError
"w" كتابة ينشئ الملف إذا كان المجلد الأب موجودًا
"a" إضافة في نهاية الملف ينشئ الملف إذا كان المجلد الأب موجودًا
"x" إنشاء ملف جديد فقط ينشئ الملف إذا كان المجلد الأب موجودًا، ويعطي خطأ إذا كان الملف موجودًا

للتوسع في أوضاع r وw وa وطرق القراءة والكتابة، راجع شرح التعامل مع الملفات في بايثون.

الحل السابع: انتبه لاستخدام الشرطة العكسية في Windows

في Windows قد تكتب مسارًا مثل:

C:\new_folder\data.txt

لكن داخل النصوص في Python قد تسبب الشرطة العكسية \ مشاكل؛ لأن بعض التركيبات مثل \n تعني سطرًا جديدًا.

لذلك يمكنك استخدام أحد هذه الحلول:

استخدام شرطة عكسية مزدوجة

path = "C:\\new_folder\\data.txt"

استخدام raw string

path = r"C:\new_folder\data.txt"

استخدام الشرطة المائلة العادية

path = "C:/new_folder/data.txt"

لكن في المشاريع التعليمية، الأفضل غالبًا أن تستخدم pathlib بدل كتابة المسارات الطويلة يدويًا.

مثال عملي كامل: قراءة ملف من مجلد المشروع بأمان

لنفترض أن main.py وملف students.txt جزء من المشروع التالي:

project/
├── main.py
└── data/
    └── students.txt

الحل الأكثر ثباتًا هو ربط المسار بمكان main.py نفسه:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent
file_path = BASE_DIR / "data" / "students.txt"

try:
    content = file_path.read_text(encoding="utf-8")
    print(content)
except FileNotFoundError:
    print("لم يتم العثور على الملف:", file_path)

بهذا الأسلوب لا يعتمد مكان الملف على المجلد الذي فتحت منه Terminal أو زر التشغيل في المحرر، لأن نقطة البداية هي مكان السكربت نفسه.

خطوات حل FileNotFoundError والمسارات الخاطئة في مشاريع بايثون

قائمة فحص سريعة لحل الخطأ

عندما يظهر لك خطأ FileNotFoundError، راجع هذه النقاط بالترتيب:

السؤال ما الذي تراجعه؟
هل الملف موجود؟ تأكد أن الملف موجود فعلًا في المشروع.
هل الاسم صحيح؟ راجع الحروف، حالة الأحرف، المسافات، والامتداد الحقيقي بما فيه الامتدادات المخفية.
هل الملف داخل مجلد؟ اكتب اسم المجلد ضمن المسار مثل data/file.txt.
من أين يعمل البرنامج؟ استخدم Path.cwd() أو os.getcwd() لمعرفة CWD.
هل الملف بجانب السكربت لكن الخطأ مستمر؟ اربط المسار بـPath(__file__).resolve().parent بدل الاعتماد على CWD.
هل تستخدم Windows؟ انتبه للشرطة العكسية أو استخدم pathlib.
هل تريد القراءة أم الإنشاء؟ استخدم "r" للقراءة، و "w" أو "a" للإنشاء أو الكتابة.

أخطاء شائعة مرتبطة بهذا الخطأ

1. إنشاء الملف في مكان وتشغيل الكود من مكان آخر

قد تضع الملف على سطح المكتب، ثم تشغل الكود من مجلد المشروع. في هذه الحالة لن يجده Python إذا كتبت اسم الملف فقط.

2. اختلاف الامتداد الحقيقي للملف

في Windows قد يظهر الملف باسم data فقط، لكنه في الحقيقة data.txt أو data.csv. تأكد من إظهار امتدادات الملفات من إعدادات النظام.

3. الاعتماد على السحب والإفلات دون معرفة المسار

قد تفتح الملف من محرر كود، لكن هذا لا يعني أن مسار التشغيل هو نفس مكان الملف. لذلك من المهم معرفة المجلد الحالي.

4. استخدام اسم مجلد خطأ

إذا كان المجلد اسمه files وكتبت file أو data، سيظهر الخطأ لأن المسار غير مطابق.

5. محاولة إنشاء ملف داخل مجلد غير موجود

حتى عند استخدام "w"، سيظهر FileNotFoundError إذا كان المجلد الأب غير موجود. أنشئ المجلد أولًا:

from pathlib import Path

output_dir = Path("output")
output_dir.mkdir(parents=True, exist_ok=True)

file_path = output_dir / "report.txt"
file_path.write_text("تم إنشاء التقرير", encoding="utf-8")

مثال خطأ وحله

لنفترض أن هيكل المشروع هكذا:

my_project/
│
├── main.py
└── data/
    └── names.txt

الكود الخطأ:

with open("names.txt", "r", encoding="utf-8") as file:
    print(file.read())

سبب الخطأ أن الملف داخل مجلد data. الحل:

with open("data/names.txt", "r", encoding="utf-8") as file:
    print(file.read())

أو باستخدام pathlib:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent
file_path = BASE_DIR / "data" / "names.txt"

with file_path.open("r", encoding="utf-8") as file:
    print(file.read())

روابط داخلية مفيدة من بايثون العرب

مصادر خارجية مفيدة للتوسع

الخلاصة

خطأ FileNotFoundError: [Errno 2] No such file or directory يعني أن بايثون لم يجد الملف أو المجلد في المسار المطلوب. إذا كان الملف موجودًا فعلًا، افحص CWD أولًا؛ فالمسارات النسبية تعتمد على مجلد العمل الحالي وليس بالضرورة مجلد السكربت.

ابدأ بـPath.cwd() أو os.getcwd()، ثم راجع الاسم والامتداد وحالة الأحرف. ولملفات المشروع التي يجب أن تكون مرتبطة بمكان السكربت، استخدم Path(__file__).resolve().parent. وإذا كان غياب الملف احتمالًا طبيعيًا، تعامل معه بـtry/except بعد التأكد أن المسار نفسه صحيح.

الخلاصة العملية: لا تخفِ FileNotFoundError مباشرة. اطبع المسار الذي يحاول Python فتحه، واعرف CWD، ثم أصلح سبب المسار أولًا.

أسئلة شائعة مع إجاباتها

ما معنى FileNotFoundError في Python؟

يعني أن Python حاول فتح ملف أو مسار لكنه لم يجده في المكان الذي يبحث فيه.

هل يعني الخطأ أن الملف غير موجود نهائيًا؟

ليس دائمًا. قد يكون الملف موجودًا، لكن Python يبحث عنه في مجلد آخر أو أن المسار المكتوب غير صحيح.

كيف أعرف المجلد الحالي الذي يعمل منه Python؟

استخدم Path.cwd() أو os.getcwd(). هذا هو المجلد الذي تُفسَّر نسبةً إليه المسارات مثل "data.txt".

لماذا يظهر FileNotFoundError والملف موجود بجانب السكربت؟

لأن CWD قد يكون مختلفًا عن مجلد السكربت. إذا كان الملف جزءًا ثابتًا من المشروع، ابنِ المسار من Path(__file__).resolve().parent بدل الاعتماد على CWD.

ما الفرق بين r و w عند فتح الملفات؟

الوضع "r" يستخدم للقراءة ويحتاج أن يكون الملف موجودًا. أما "w" فيستخدم للكتابة وينشئ الملف إذا لم يكن موجودًا، لكنه قد يستبدل محتوى الملف إذا كان موجودًا.

هل pathlib أفضل من open العادي؟

ليست بديلة عن open دائمًا، لكنها تساعدك على بناء المسارات وفحص الملفات بطريقة أوضح وأكثر تنظيمًا، خصوصًا في المشاريع العملية.

كيف أتجنب FileNotFoundError؟

تأكد من اسم الملف وامتداده والمجلد الأب، واعرف CWD، واستخدم مسارًا ثابتًا مناسبًا للمشروع. استخدم pathlib لبناء المسارات وtry/except عندما يكون غياب الملف حالة متوقعة.

هل وضع w ينشئ المجلد إذا لم يكن موجودًا؟

لا. "w" ينشئ الملف إذا كان المجلد الأب موجودًا، لكنه لا ينشئ المجلدات المفقودة. أنشئها أولًا باستخدام Path.mkdir(parents=True, exist_ok=True).

Admin
Admin
تعليقات