بعد أن تبدأ في قراءة الملفات النصية أو ملفات CSV في Python، قد يظهر لك خطأ مزعج اسمه UnicodeDecodeError. هذا الخطأ يظهر غالبًا عندما يحاول Python قراءة ملف بترميز معين، بينما الملف نفسه محفوظ بترميز مختلف.
في هذا المقال من سلسلة مشكلة وحل في بايثون على موقع بايثون العرب سنشرح معنى خطأ UnicodeDecodeError، ولماذا يظهر عند قراءة الملفات، وما علاقة encoding بالمشكلة، وكيف تحل الخطأ عند التعامل مع ملفات نصية أو ملفات CSV، خصوصًا عندما تحتوي الملفات على نصوص عربية.
{getToc} $title={محتوى المقال}
الفكرة ببساطة: خطأ UnicodeDecodeError يعني أن Python حاول قراءة الملف بترميز غير مناسب، فلم يستطع تحويل بعض البايتات إلى نص مفهوم. {alertInfo}
شكل الخطأ
قد يظهر الخطأ بأكثر من صيغة. من أشهر الرسائل:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x... in position ...
وقد يظهر أيضًا بهذا الشكل على Windows:
UnicodeDecodeError: 'charmap' codec can't decode byte 0x... in position ...
أو عند قراءة ملف CSV:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x81 in position 10: invalid start byte
رغم أن الرسائل تبدو معقدة، إلا أن معناها بسيط: Python استخدم ترميزًا لا يناسب الملف.
مثال يسبب UnicodeDecodeError
لنفترض أن لديك ملفًا اسمه students.csv يحتوي على أسماء عربية، لكنه محفوظ بترميز مختلف عن utf-8. ثم كتبت الكود التالي:
with open("students.csv", "r", encoding="utf-8") as file:
content = file.read()
print(content)
إذا كان الملف غير محفوظ بترميز utf-8، فقد يظهر خطأ UnicodeDecodeError.
ما معنى UnicodeDecodeError؟
لفهم الخطأ، نحتاج إلى تبسيط الفكرة. الملفات داخل الكمبيوتر لا تُخزن كأحرف مباشرة، بل تُخزن كبايتات. وعندما يقرأ Python الملف كنص، يحتاج إلى معرفة الطريقة الصحيحة لتحويل هذه البايتات إلى أحرف.
هذه الطريقة تسمى encoding أو الترميز.
إذا كان الملف محفوظًا بترميز معين، وحاول Python قراءته بترميز آخر، قد يفشل التحويل وتظهر رسالة UnicodeDecodeError.
مثال مبسط:
- الملف محفوظ بترميز
cp1256. - أنت تحاول قراءته باستخدام
utf-8. - Python يجد بايتات لا يستطيع تفسيرها كـ UTF-8.
- فتظهر رسالة
UnicodeDecodeError.
ما هو encoding في Python؟
encoding هو الترميز المستخدم لقراءة أو كتابة النصوص داخل الملفات. عند فتح ملف نصي في Python، يمكنك تحديد الترميز هكذا:
open("file.txt", "r", encoding="utf-8")
أشهر الترميزات التي قد تصادفها:
| الترميز | متى يستخدم؟ | ملاحظة |
|---|---|---|
utf-8 |
الأكثر استخدامًا حاليًا | مناسب للعربية والإنجليزية ومعظم اللغات |
utf-8-sig |
ملفات UTF-8 التي تحتوي على BOM | مفيد لبعض ملفات Excel أو Windows |
cp1256 |
بعض الملفات العربية القديمة على Windows | قد يحل مشاكل ملفات عربية محفوظة كـ ANSI |
latin-1 |
بعض الملفات الغربية القديمة | يقرأ أغلب البايتات لكنه قد يعطي نصًا غير صحيح |
قاعدة مهمة: لا يوجد ترميز واحد يصلح لكل الملفات. الأفضل أن تعرف ترميز الملف أو تجرب الترميز المناسب حسب مصدر الملف. {alertWarning}
السبب الأول: قراءة ملف بترميز خاطئ
هذا هو السبب الأشهر. يكون الملف محفوظًا بترميز معين، لكنك تقرأه بترميز مختلف.
مثال قد يسبب الخطأ:
with open("arabic_file.txt", "r", encoding="utf-8") as file:
text = file.read()
إذا كان الملف محفوظًا بترميز cp1256 مثلًا، جرّب:
with open("arabic_file.txt", "r", encoding="cp1256") as file:
text = file.read()
print(text)
إذا اختفى الخطأ وظهر النص العربي بشكل صحيح، فالمشكلة كانت في الترميز.
السبب الثاني: استخدام الترميز الافتراضي بدون تحديد encoding
بعض المبتدئين يفتحون الملف هكذا:
with open("data.txt", "r") as file:
content = file.read()
قد يعمل هذا أحيانًا، لكنه ليس أفضل أسلوب؛ لأن Python سيستخدم الترميز الافتراضي للنظام. وقد يختلف هذا الترميز من جهاز لآخر.
الأفضل أن تكتب الترميز صراحة:
with open("data.txt", "r", encoding="utf-8") as file:
content = file.read()
هذا يجعل الكود أوضح وأكثر قابلية للنقل بين الأجهزة.
السبب الثالث: ملف CSV صادر من Excel
كثير من مشاكل UnicodeDecodeError تظهر عند قراءة ملفات CSV تم تصديرها من Excel، خصوصًا إذا كانت تحتوي على نصوص عربية.
قد يكون الملف محفوظًا بترميز غير utf-8، أو يحتوي على علامة خاصة في البداية تسمى BOM. في هذه الحالة جرّب utf-8-sig.
import csv
with open("students.csv", "r", encoding="utf-8-sig") as file:
reader = csv.reader(file)
for row in reader:
print(row)
إذا لم ينجح utf-8-sig، وكنت تتعامل مع ملف عربي قديم من Windows، جرّب cp1256.
with open("students.csv", "r", encoding="cp1256") as file:
content = file.read()
print(content)
السبب الرابع: محاولة قراءة ملف غير نصي كنص
أحيانًا يظهر الخطأ لأنك تحاول قراءة ملف ليس نصيًا أصلًا، مثل صورة أو ملف PDF أو ملف Excel بامتداد .xlsx باستخدام open() كنص.
مثال خاطئ:
with open("report.xlsx", "r", encoding="utf-8") as file:
content = file.read()
ملف .xlsx ليس ملفًا نصيًا بسيطًا مثل CSV، لذلك لا تقرأه بهذه الطريقة. إذا أردت التعامل مع Excel، استخدم مكتبة مناسبة مثل openpyxl.
الحل الأول: استخدم encoding="utf-8"
إذا كنت أنت من ينشئ الملف أو تتحكم في طريقة حفظه، اجعل الترميز utf-8 واستخدمه عند القراءة والكتابة.
كتابة ملف نصي بترميز UTF-8:
with open("message.txt", "w", encoding="utf-8") as file:
file.write("مرحبًا بك في بايثون العرب")
قراءة نفس الملف:
with open("message.txt", "r", encoding="utf-8") as file:
text = file.read()
print(text)
هذا هو الأسلوب الأفضل في المشاريع الجديدة.
الحل الثاني: استخدم utf-8-sig مع بعض ملفات CSV
إذا كان ملف CSV صادرًا من Excel أو يحتوي على مشكلة في بداية أول عمود، جرّب utf-8-sig.
import csv
with open("data.csv", "r", encoding="utf-8-sig") as file:
reader = csv.DictReader(file)
for row in reader:
print(row)
هذا الحل مفيد عندما يكون الملف UTF-8 لكنه يحتوي على BOM في البداية.
الحل الثالث: استخدم cp1256 للملفات العربية القديمة
إذا كان الملف عربيًا وقديمًا أو محفوظًا من برنامج على Windows بصيغة ANSI، فقد يكون الترميز المناسب هو cp1256.
with open("arabic_data.txt", "r", encoding="cp1256") as file:
content = file.read()
print(content)
إذا ظهر النص العربي بشكل صحيح، فهذا يعني أن الترميز كان مناسبًا.
الحل الرابع: استخدام errors عند الحاجة
في بعض الحالات تريد قراءة الملف حتى لو كانت فيه أحرف غير قابلة للفهم. هنا يمكنك استخدام الخيار errors.
مثال باستخدام replace:
with open("data.txt", "r", encoding="utf-8", errors="replace") as file:
content = file.read()
print(content)
هذا يستبدل الأحرف غير المفهومة برمز بديل بدل إيقاف البرنامج.
ويمكنك أيضًا استخدام ignore:
with open("data.txt", "r", encoding="utf-8", errors="ignore") as file:
content = file.read()
لكن انتبه: استخدام ignore قد يحذف بعض الأحرف من النص، لذلك لا تستخدمه إلا عند الضرورة.
تحذير: خيار errors="ignore" قد يخفي المشكلة ويحذف أحرفًا من النص. الأفضل معرفة الترميز الصحيح بدل تجاهل الخطأ. {alertWarning}
طريقة حل UnicodeDecodeError خطوة بخطوة
عندما يظهر الخطأ، اتبع هذه الخطوات بدل تجربة حلول عشوائية:
- تأكد أن الملف نصي فعلًا وليس صورة أو Excel أو PDF.
- حدد مصدر الملف: هل هو من Excel؟ من نظام قديم؟ من موقع؟
- جرّب أولًا
encoding="utf-8". - إذا كان الملف من Excel، جرّب
encoding="utf-8-sig". - إذا كان الملف عربيًا قديمًا من Windows، جرّب
encoding="cp1256". - إذا ظهر النص مشوهًا، فربما الترميز ما زال غير صحيح.
- استخدم
errors="replace"فقط إذا أردت قراءة الملف مؤقتًا مع معرفة أن هناك أحرفًا غير مفهومة. - احفظ ملفاتك الجديدة دائمًا بترميز UTF-8.
مثال عملي: قراءة CSV عربي بدون خطأ
لنفترض أن لديك ملفًا اسمه students.csv يحتوي على:
الاسم,المدينة
علي,عدن
سارة,صنعاء
جرّب أولًا قراءة الملف باستخدام UTF-8:
import csv
with open("students.csv", "r", encoding="utf-8") as file:
reader = csv.reader(file)
for row in reader:
print(row)
إذا ظهر خطأ، جرّب:
with open("students.csv", "r", encoding="utf-8-sig") as file:
reader = csv.reader(file)
for row in reader:
print(row)
وإذا كان الملف محفوظًا بترميز عربي قديم، جرّب:
with open("students.csv", "r", encoding="cp1256") as file:
reader = csv.reader(file)
for row in reader:
print(row)
استخدام try و except مع UnicodeDecodeError
يمكنك التعامل مع الخطأ باستخدام try و except حتى تعرض رسالة واضحة بدل توقف البرنامج.
try:
with open("data.txt", "r", encoding="utf-8") as file:
content = file.read()
print(content)
except UnicodeDecodeError:
print("تعذر قراءة الملف بسبب مشكلة في الترميز.")
print("جرّب encoding='utf-8-sig' أو encoding='cp1256' حسب مصدر الملف.")
هذا لا يحل الترميز تلقائيًا، لكنه يجعل البرنامج أوضح للمستخدم.
تجربة أكثر من ترميز تلقائيًا
في بعض المشاريع البسيطة، يمكنك تجربة أكثر من ترميز حتى ينجح أحدها.
encodings = ["utf-8", "utf-8-sig", "cp1256"]
for enc in encodings:
try:
with open("data.txt", "r", encoding=enc) as file:
content = file.read()
print("تمت القراءة باستخدام:", enc)
print(content)
break
except UnicodeDecodeError:
print("فشل الترميز:", enc)
هذا المثال مفيد تعليميًا، لكنه لا يغني عن معرفة الترميز الصحيح للملف.
تحويل ملف إلى UTF-8
إذا عرفت أن ملفًا عربيًا محفوظ بترميز cp1256 وتريد تحويله إلى utf-8، يمكنك قراءته بالترميز القديم ثم كتابته من جديد بترميز UTF-8.
with open("old_file.txt", "r", encoding="cp1256") as file:
content = file.read()
with open("new_file_utf8.txt", "w", encoding="utf-8") as file:
file.write(content)
بهذا يصبح لديك ملف جديد بترميز UTF-8، وهو أسهل للتعامل معه لاحقًا.
الفرق بين UnicodeDecodeError و UnicodeEncodeError
قد ترى أحيانًا خطأ آخر اسمه UnicodeEncodeError. الفرق بينهما:
| الخطأ | متى يحدث؟ | المعنى |
|---|---|---|
UnicodeDecodeError |
عند قراءة ملف أو تحويل بايتات إلى نص | Python لم يستطع فك الترميز |
UnicodeEncodeError |
عند كتابة نص إلى ملف أو تحويل نص إلى بايتات | Python لم يستطع ترميز النص |
مقالنا هنا يركز على UnicodeDecodeError لأنه يظهر غالبًا عند قراءة الملفات.
مقارنة سريعة بين الحلول
| الحالة | الحل المقترح |
|---|---|
| ملف حديث أو أنت من أنشأته | encoding="utf-8" |
| ملف CSV من Excel وفيه مشكلة بداية الملف | encoding="utf-8-sig" |
| ملف عربي قديم من Windows | encoding="cp1256" |
| تريد قراءة الملف مؤقتًا رغم وجود أحرف مشكلة | errors="replace" |
| الملف ليس نصيًا مثل xlsx أو pdf | استخدم مكتبة مناسبة لنوع الملف |
أفضل ممارسات لتجنب UnicodeDecodeError
- حدد
encodingدائمًا عند قراءة وكتابة الملفات النصية. - استخدم
utf-8في المشاريع الجديدة قدر الإمكان. - استخدم
utf-8-sigعند التعامل مع بعض ملفات CSV الصادرة من Excel. - جرّب
cp1256مع الملفات العربية القديمة المحفوظة من Windows. - لا تقرأ ملفات
.xlsxأو الصور أو PDF كملفات نصية عادية. - استخدم
errors="replace"بحذر عندما تحتاج قراءة مؤقتة للملف. - وحّد ترميز ملفات مشروعك إلى UTF-8 لتقليل المشاكل.
- اكتب ملاحظة في مشروعك عن الترميز المستخدم للملفات.
تدريب عملي
أنشئ ملفًا نصيًا باسم arabic.txt واكتب فيه نصًا عربيًا، ثم احفظه بترميز UTF-8 إن استطعت. بعد ذلك اقرأه باستخدام Python:
with open("arabic.txt", "r", encoding="utf-8") as file:
text = file.read()
print(text)
ثم جرّب قراءة ملف CSV عربي باستخدام utf-8، وإذا ظهرت مشكلة جرّب utf-8-sig ثم cp1256.
حل مختصر للتدريب
encodings = ["utf-8", "utf-8-sig", "cp1256"]
for enc in encodings:
try:
with open("arabic.txt", "r", encoding=enc) as file:
text = file.read()
print("الترميز الصحيح غالبًا:", enc)
print(text)
break
except UnicodeDecodeError:
pass
روابط داخلية مفيدة من بايثون العرب
- سلسلة مشكلة وحل في بايثون
- أساسيات بايثون 30: شرح ملفات CSV في Python للمبتدئين
- أساسيات بايثون 22: التعامل مع الملفات في Python
- أساسيات بايثون 29: شرح مكتبة json في Python
- حل خطأ FileNotFoundError في Python عند فتح الملفات
- حل خطأ JSONDecodeError في Python عند قراءة ملفات JSON
مصادر خارجية مفيدة للتوسع
الخلاصة
خطأ UnicodeDecodeError يحدث عندما يحاول Python قراءة ملف بترميز غير مناسب. المشكلة ليست دائمًا في الكود نفسه، بل غالبًا في أن الملف محفوظ بترميز مختلف عن الترميز الذي تستخدمه عند القراءة.
أفضل حل في المشاريع الجديدة هو توحيد الملفات على utf-8 وكتابة encoding="utf-8" بوضوح عند القراءة والكتابة. أما ملفات CSV القادمة من Excel فقد تحتاج إلى utf-8-sig، والملفات العربية القديمة من Windows قد تحتاج إلى cp1256.
الخلاصة العملية: إذا ظهر لكUnicodeDecodeError، لا تغيّر الكود عشوائيًا. اسأل أولًا: ما ترميز الملف؟ ثم جرّبutf-8أوutf-8-sigأوcp1256حسب مصدر الملف. {alertSuccess}
أسئلة شائعة مع إجاباتها
ما معنى UnicodeDecodeError في Python؟
يعني أن Python لم يستطع تحويل محتوى الملف من بايتات إلى نص بسبب استخدام ترميز غير مناسب.
ما سبب UnicodeDecodeError عند قراءة ملف CSV؟
غالبًا يكون ملف CSV محفوظًا بترميز مختلف عن الترميز المستخدم في الكود، مثل قراءة ملف cp1256 باستخدام utf-8.
ما أفضل encoding للملفات العربية في Python؟
في المشاريع الجديدة استخدم utf-8. أما بعض الملفات العربية القديمة من Windows فقد تحتاج إلى cp1256.
متى أستخدم utf-8-sig؟
استخدمه عند قراءة ملفات UTF-8 تحتوي على BOM، وهذا يحدث أحيانًا مع ملفات CSV الصادرة من Excel.
هل errors="ignore" حل جيد؟
ليس دائمًا. قد يخفي المشكلة ويحذف أحرفًا من النص، لذلك الأفضل معرفة الترميز الصحيح أولًا.
هل يمكن قراءة ملف Excel xlsx باستخدام open كنص؟
لا. ملف Excel ليس ملفًا نصيًا عاديًا. استخدم مكتبة مناسبة مثل openpyxl عند التعامل مع ملفات .xlsx.



