الدالة open()
في بايثون
تفتح الدّالة open()
ملفّا وتعيد كائن ملفّ (file object) مرتبط به.
إن لم يُمكِن فتح الملفّ، فسيُطلَق الاستثناء OSError
.
البنية العامة
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
المعاملات
file
كائن مُشابه للمسارات (path-like object) يُمثّل مسار الملفّ (سواء أكان مُطلقا أو نسبيًّا) المرغوب فتحه.
يُمكن كذلك أن يكون واصف ملفّ عدديّ (integer file descriptor) للملفّ لتغطيّته (wrap). إن مُرّر واصف ملفّات، فسيُغلَق عندما يُغلَق كائن I/O المُعاد، إلّا في حالة كانت قيمة المُعامل closefd
تساوي False
.
mode
مُعامل اختياريّ.
سلسلة نصيّة تُحدّد الوضع الذي سيُفتح فيه الملفّ. القيمة الافتراضيّة هي 'r'
والتي تعني أنّ الملفّ سيُفتح في وضع القراءة. ومن القيم الشّائعة:
'w'
لفتح الملفّ في وضع الكتابة (مع حذف الملفّ إن كان موجودًا مُسبقًا).'x'
لإنشاء الملفّات حصرًا.'a'
لإضافة المحتويات إلى نهاية الملفّ دون حذفه إن كان موجودًا مُسبقًا (والتي تعني في بعض أنظمة يونكس أنّ الكتابة ستكون دائمًا على نهاية الملفّ بغضّ النّظر عن موقع المؤشر الحاليّ).
والأوضاع المُتاحة هي كالتّالي:
المحرف | المعنى |
---|---|
'r'
|
فتح الملفّ للقراءة (الوضع الافتراضيّ) |
'w'
|
فتح الملفّ للكتابة، مع حذف محتويات الملفّ إن كان موجودًا |
'x'
|
فتح الملفّ للإنشاء حصرًا، أي أنّ فتح الملفّ سيفشل إن كان موجودًا مُسبقًا |
'a'
|
فتح الملفّ للكتابة مع الكتابة إلى نهاية الملفّ إن كان موجودًا مُسبقًا |
'b'
|
الوضع الثّنائي (binary mode) |
't'
|
وضع النّصوص (الوضع الافتراضيّ) |
'+'
|
فتح ملفّ على القرص لتعديله (القراءة والكتابة) |
'U'
|
وضع الأسطر الجديدة العامّة (universal newlines) وهو وضع مُهمل لا يجب استخدامه. |
الوضع الافتراضي هو 'r'
(لفتح الملفّ لقراءة النّصوص، وهو نفسه الوضع 'rt'
). للقراءة والكتابة للملفّ بشكل ثُنائيّ، يُمكن استخدام الوضع 'w+b'
لفتح ملفّ وحذف محتوياته إلى 0 بايت. والوضع 'r+b'
يفتح الملفّ دون حذف محتوياته.
وكما ذُكر في تمهيد الوحدة io، لغة بايثون تُفرّق بين كائنات I/O الثّنائية وكائنات I/O النّصيّة. تُعيد الملفّات المفتوحة في الوضع الثّنائي (أي عندما يشمل الوضع المحرف 'b'
) المحتويات على شكل كائنات بايتات دون فكّ ترميزها (decoding). وأمّا في الوضع النّصيّ (وهو الوضع الافتراضيّ، أو عندما يشمل الوضع المحرف 't'
)، فتُعاد المحتويات على شكل سلاسل نصيّة، وذلك عبر فكّ ترميز البايتات أولًا باستخدام ترميز يعتمد على نظام التّشغيل أو باستخدام التّرميز المُمرّر للمُعامل encoding
.
مُلاحظة: لا تعتمد بايثون على نظام التّشغيل لمعالجة الملفّات النّصيّة، إذ تُعالَج باستخدام لغة بايثون نفسها ما يجعلها مستقلّة عن المنصّة التي تعمل فيها.
buffering
مُعامل اختياريّ.
عدد صحيح يُستعمل لضبط سياسة التّخزين الانتقاليّ (buffering). مرّر القيمةَ 0
لتعطيل التخزين الانتقاليّ (مسموح به في الوضع الثّنائيّ فقط)، أو القيمةَ 1
لاختيار تخزين الأسطر (line buffering) والذي يكون مسموحًا به في الوضع النّصيّ فقط، أو مرّر عددًا صحيحًا أكبر من واحد لتحديد حجم البايتات لمخزن قطع ثابت الحجم (fixed-size chunk buffer).
عندما لا تُمرّر أيّة مُعاملات إلى المُعامل buffering
فستعمل سياسة التّخزين الانتقاليّ كما يلي:
- تُخزّن الملفّات الثّنائيّة في قطع ثابتة الحجم؛ يُحدَّدُ حجم المخزن عبر محاولة الحصول على حجم القطع (block size) الخاصّ بالجهاز، أو تُستعمل القيمة
io.DEFAULT_BUFFER_SIZE
إن فشلت المُحاولة. يكون حجم المخزن في العديد من الأنظمة عادةً إمّا 4096 أو 8192 بايت.
- تستعمل الملفّات النّصيّة التّفاعليّة (التي يُعيد فيها استدعاء التّابع
isatty()
القيمةTrue
) تخزين الأسطر. أمّا الملفّات النّصيّة الأخرى فتستعمل سياسة الملفّات الثّنائية الموضّحة أعلاه.
encoding
مُعامل اختياريّ.
اسم التّرميز الذي سيُستعمل لفكّ ترميز وترميز الملفّ. يجب استخدامه فقط في وضع الملفّات النّصيّة. في وضع الملفّات النّصيّة، إن لم تُمرّر قيمة للمُعامل encoding
فالتّرميز المستخدم سيعتمد على نظام التّشغيل، وسيُستعمل الاستدعاء locale.getpreferredencoding(False)
للحصول على التّرميز المحليّ. (ولقراءة وكتابة البايتات الخام، استعمل الوضع الثّنائي واترك تحديد قيمة للمُعامل encoding
.) لكن يُمكن استخدام أي ترميز نصوص تدعمه بايثون. انظر الوحدة codecs
للحصول على قائمة بالتّرميزات المدعومة.
errors
مُعامل اختياريّ.
سلسلة نصيّة تُحدّد كيفيّة مُعالجة أخطاء ترميز الملفّات وفكّ ترميزها. ولا يُمكن استخدامه في الوضع الثّنائي. هناك العديد من مُعالجات الأخطاء القياسيّة المتوفّرة (انظر قائمة معالجات الأخطاء)، لكن يُمكن كذلك استعمال أي اسم مُعالج أخطاء مُسجّل بالدّالة codecs.register_error()
. أسماء مُعالجات الأخطاء القياسيّة تشمل ما يلي:
'strict'
لإطلاق استثناءValueError
إن حدث خطأ في التّرميز. والقيمة الافتراضيّة للمُعامل (أي القيمةNone
) لها نفس التأثير.'ignore'
لتجاهل الأخطاء. لكن انتبه إلى أنّ تجاهل أخطاء التّرميز قد يتسبّب في فقدان البيانات.'replace'
لإبدال البيانات المشوّهة (التي حدثت عندها مشاكل في التّرميز) بعلامة مثل'?'
.'surrogateescape'
سيُمثّل أية بايتات غير صالحة لتكون على شكل نقاط شيفرة (code points) في مساحة الاستخدام الخاصّة ليونيكود (Unicode Private Use Area) ضمن المجال U+DC80 إلى U+DCFF. ستُرجع بعد ذلك نقاط الشّيفرة الخاصّة هذه إلى نفس البايتات عندما يُستعمل مُعالج الأخطاءsurrogateescape
لكتابة البيانات. وهذا مُفيد لمُعالجة الملفّات مجهولة التّرميز.'xmlcharrefreplace'
مدعوم فقط عند الكتابة إلى ملفّ. ويقوم بإبدال المحارف غير المدعومة من طرف التّرميز إلى مرجع المحرف في مراجع XML (على شاكلة&#nnn;
).'backslashreplace'
يُبدِل البيانات المُشوّهة بسلاسل التّهريب المسبوقة بالمحرف\
في بايثون.'namereplace'
مدعوم عند الكتابة فقط. يُبدل المحارف غير المدعومة بسلاسل التّهريب\N{...}
.
newline
مُعامل اختياريّ.
يتحكّم بكيفيّة عمل وضع الأسطر الجديدة العامّ (universal newlines mode) في الوضع النّصيّ. يُمكن للقيم أن تكون None
، أو ، أو '\n'
، أو '\r'
، أو '\r\n'
. وتعمل كما يلي:
- عند قراءة المُدخلات من التّيار (stream)، يكون وضع الأسطر الجديدة العامّ مُفعّلًا إن كانت قيمة المعامل
newline
تُساويNone
. يُمكن للأسطر في المُدخل أن تنتهي بالمقطع'\n'
، أو'\r'
، أو '\r\n'
وستُترجم إلى'\n'
قبل إعادتها إلى المُستدعي. وإن كانت قيمة المعاملnewline
تُساوي''
فإنّ وضع الأسطر الجديدة العامّ يكون مُفعّلًا، لكنّ نهايات الأسطر تُعاد إلى المُستدعِي دون ترجمتها. وإن كانت قيمة المعاملnewline
تُساوي أيًّا من القيم الأخرى المسموح بها، فستنتهي الأسطر بالقيمة المُعطاة فقط، وستُعاد نهايات الأسطر إلى المُستدعِي دون ترجمتها. - عند الكتابة إلى الملفّ، إن كانت قيمة المعامل
newline
تُساويNone
، فستُترجم أيّة محارف'\n'
إلى فاصل الأسطر الافتراضي لنظام التّشغيل، والذي يُمكن الوصول إليه عبر الخاصيّةos.linesep
. وإن كانت قيمة المعاملnewline
تُساوي''
أو'\n'
فلن تُترجم نهايات الأسطر. وإن كانت قيمة المعاملnewline
تُساوي أيًّا من القيم الأخرى المسموح بها، فستُترجم أيّة محارف'\n'
إلى القيمة المُعطاة.
closefd
مُعامل اختياريّ.
إن كانت قيمته تُساوي القيمة False
وإن أعطِيَ واصف ملفّ (file descriptor) عوضًا عن اسم ملفّ للمُعامل file
، فسيبقى واصف الملفّ مفتوحًا عندما يُغلق الملفّ. إن أُعطيَ اسم ملفّ للمُعامل file
فيجب على قيمة المُعامل closefd
أن تُساوي True
(وهي القيمة الافتراضيّة)، وإلّا سيُطلق استثناء ValueError
.
opener
مُعامل اختياريّ.
يُستعمل هذا المُعامل لاستعمال فاتح ملفّات خاصّ عبر تمريره (على شكل كائنٍ قابل للاستدعاء) إلى المُعامل opener
. ويُستخرج واصف الملفّ الضّمني لكائن الملفّ عبر استدعاء الكائن المُمرّر إلى المُعامل opener
بالمُعاملات المُعطاة. ويجب على الكائن المُعطى أن يُعيد واصف ملفّ مفتوحًا (تمرير الدّالة os.open
كفاتح ملفّات له تأثير مُشابه لتمرير القيمة None
الافتراضيّة). لاحظ أنّ الملفّ المُنشأ حديثًا غير قابل للوراثة (non-inheritable).
القيمة المعادة
كائن ملفّ يعتمد نوعه على الوضع الذي فُتح فيه الملفّ:
- إن استُخدمت الدّالة
open()
لفتح ملفّ في الوضع النّصيّ (إمّا'w'
أو'r'
أو'wt'
أو'rt'
)، فستُعيد صنفًا فرعيًّا من الصّنفio.TextIOBase
(الصّنفio.TextIOWrapper
على وجه التّحديد). - إن استُخدمت لفتح ملفّ في الوضع الثّنائي (binary mode) مع التّخزين الانتقاليّ، فالصّنف المُعاد صنفٌ فرعيّ من الصّنف
io.BufferedIOBase
. والصّنف ذاته يختلف، ففي وضع القراءة الثّنائيّ، سيُعادio.BufferedReader
؛ وفي وضع الكتابة (والكتابة إلى آخر الملفّ) الثّنائيّ، سيُعادio.BufferedWriter
، أمّا في وضع القراءة والكتابة، فيُعادio.BufferedRandom
وإن عُطّل التّخزين الانتقاليّ، فسيُعاد التّيار الخام، والذي يكون صنفًا فرعيًّا منio.RawIOBase
أوio.FileIO
.
أمثلة
المثال التّالي يوضّح كيفيّة عمل هذه الدّالة لفتح ملفّ باسم name.txt
وكتابة القيمة Ali
إليه:
>>> with open('name.txt', 'w') as f:
... f.write('Ali')
...
المثال التّالي يستعمل المُعامل dir_fd
الخاصّ بالدّالة os.open
لفتح ملفّ نسبةً إلى مُجلّد مُعطى:
>>> import os
>>> dir_fd = os.open('somedir', os.O_RDONLY)
>>> def opener(path, flags):
... return os.open(path, flags, dir_fd=dir_fd)
...
>>> with open('spamspam.txt', 'w', opener=opener) as f:
... print('somedir/spamspam.txt', file=f) # تطبع مسار الملفّ الذي سيُكتب إليه السّطر
...
>>> os.close(dir_fd) # أغلق واصف الملفّ