الفرق بين المراجعتين لصفحة: «Python/configparser»
لا ملخص تعديل |
لا ملخص تعديل |
||
(2 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة) | |||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:الوحدة <code>configparser</code> في بايثون}}</noinclude> | |||
تقدّم هذه الوحدة الصنف <code>[[Python/ConfigParser|ConfigParser]]</code> الذي يستخدم لغة إعدادات بسيطة تقدّم بنية مشابهة للبنية التي تقدّمها ملفات INI في نظام Microsoft Windows. ويمكن استخدام هذا الصنف لكتابة برامج وتطبيقات يمكن للمستخدمين تخصيصها بكل سهولة. | تقدّم هذه الوحدة الصنف <code>[[Python/ConfigParser|ConfigParser]]</code> الذي يستخدم لغة إعدادات بسيطة تقدّم بنية مشابهة للبنية التي تقدّمها ملفات INI في نظام Microsoft Windows. ويمكن استخدام هذا الصنف لكتابة برامج وتطبيقات يمكن للمستخدمين تخصيصها بكل سهولة. | ||
سطر 181: | سطر 182: | ||
=== الصنف <code>configparser.ExtendedInterpolation</code> === | === الصنف <code>configparser.ExtendedInterpolation</code> === | ||
طريقة أخرى لاستيفاء القيم وتستخدم صيغة أكثر تقدّمًا، وتستخدم في حزمة zc.buildout على سبيل المثال. يُقصد بالاستيفاء الموسّع Extended interpolation استخدام الصيغة ${section:option} للإشارة إلى قيمة في قسم آخر. يمكن للاستيفاء أن يمتد لمستويات متعددة، وإن حذف الجزء section: من الصيغة فإنّ عملية الاستيفاء تكون ضمن القسم الحالي افتراضيًا (ومن المحتمل أن تُستوفى القيم الافتراضية من القسم الخاص). | طريقة أخرى لاستيفاء القيم وتستخدم صيغة أكثر تقدّمًا، وتستخدم في حزمة [https://pypi.org/project/zc.buildout/ zc.buildout] على سبيل المثال. يُقصد بالاستيفاء الموسّع Extended interpolation استخدام الصيغة <code>${section:option}</code> للإشارة إلى قيمة في قسم آخر. يمكن للاستيفاء أن يمتد لمستويات متعددة، وإن حذف الجزء <code>section</code>: من الصيغة فإنّ عملية الاستيفاء تكون ضمن القسم الحالي افتراضيًا (ومن المحتمل أن تُستوفى القيم الافتراضية من القسم الخاص). | ||
فعلى سبيل المثال، ستظهر الإعدادات التي مرّ ذكرها في قسم الاستيفاء العادي بالمظهر التالي في الاستيفاء الموسّع:<syntaxhighlight lang="cfg"> | |||
[Paths] | [Paths] | ||
home_dir: /Users | home_dir: /Users | ||
my_dir: ${home_dir}/lumberjack | my_dir: ${home_dir}/lumberjack | ||
my_pictures: ${my_dir}/Pictures | my_pictures: ${my_dir}/Pictures | ||
</syntaxhighlight>يمكن جلب قيم من أقسام أخرى أيضًا:<syntaxhighlight lang="cfg"> | |||
يمكن جلب قيم من أقسام أخرى أيضًا: | |||
[Common] | [Common] | ||
home_dir: /Users | home_dir: /Users | ||
سطر 208: | سطر 206: | ||
my_pictures: ${my_dir}/Pictures | my_pictures: ${my_dir}/Pictures | ||
python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python} | python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python} | ||
</syntaxhighlight> | |||
الوصول إلى القيم باستخدام بروتوكول الربط | == الوصول إلى القيم باستخدام بروتوكول الربط Mapping Protocol == | ||
'''ملاحظة''': هذا البروتوكول جديد في الإصدار 3.2 من بايثون. | '''ملاحظة''': هذا البروتوكول جديد في الإصدار 3.2 من بايثون. | ||
يُطلق هذا الاسم على الوظيفة التي تتيح استخدام كائنات خاصة كما لو أنّها كانت قواميس. وتُستخدم الصيغة | يُطلق هذا الاسم على الوظيفة التي تتيح استخدام كائنات خاصة كما لو أنّها كانت قواميس. وتُستخدم الصيغة <code>parser['section']['option']</code> كواجهة للربط في وحدة <code>configparser</code>. | ||
يعيد الجزء | يعيد الجزء <code>parser['section']</code> وسيطًا proxy لبيانات القسم في المحلل، وهذا يعني أنّ القيم لا تنسخ ولكنّها تُؤخذ من المفسّر الأصلي عند الحاجة. ويجب التنبيه إلى أنّه عند تغيير القيم في وسيط القسم فإنّ ما يجري في الواقع هو تعديل القيم في المفسّر الأصلي. | ||
تسلك | تسلك كائنات الوحدة <code>configparser</code> سلوكًا مقاربًا [[Python/dict|للقواميس]] إلى حدٍّ كبير، وواجهة الربط كاملة وتلتزم بما يفرضه الصنف <code>[[Python/collections.abc#.D8.A7.D9.84.D8.B5.D9.86.D9.81 collections.abc.MutableMapping|MutableMapping ABC]]</code>، ولكن هناك بعض الاختلافات التي يجب أخذها بالحسبان: | ||
* جميع المفاتيح في الأقسام غير حساسة لحالة الأحرف، فعلى سبيل المثال يعيد التعبير: | * جميع المفاتيح في الأقسام غير حساسة لحالة الأحرف، فعلى سبيل المثال يعيد التعبير: | ||
<syntaxhighlight lang="python3"> | |||
for option in parser["section"] | for option in parser["section"] | ||
يعيد أسماء المفاتيح التي | </syntaxhighlight>يعيد أسماء المفاتيح التي المحوّلة بواسطة التابع <code>optionxform()</code>، أي أنّ المفاتيح تكون بالحرف الصغير افتراضيًا، وفي نفس الوقت، يعطي التعبيران التاليان النتيجة <code>True</code> لقسم يتضمّن المفتاحين: <syntaxhighlight lang="python3"> | ||
"a" in parser["section"] | "a" in parser["section"] | ||
"A" in parser["section"] | "A" in parser["section"] | ||
</syntaxhighlight> | |||
* تتضمّن جميع الأقسام كذلك قيم <code>DEFAULTSECT</code>، وهذا يعني أنّ القسم لن يبدو فارغًا إن استدعي التابع clear() على ذلك القسم؛ وذلك لعدم إمكانية حذف القيم الافتراضية من القسم (لأنّها ليست موجودة فيه أصلًا)، وإن كان القسم يعيد تعريف القيم الافتراضية، فإنّ حذف القيم الجديدة في القسم سيتسبب في إعادة إظهار القيم الافتراضية. يؤدي حذف أيّ قيمة افتراضية إلى إطلاق الخطأ <code>KeyError</code>. | |||
* لا يمكن حذف <code>DEFAULTSECT</code> من المفسّر: | |||
** يؤدي حذفه إلى إطلاق الخطأ <code>ValueError</code> | |||
* لا يمكن حذف DEFAULTSECT من المفسّر: | ** لا يؤثر استدعاء التابع <code>parser.clear()</code> عليه إطلاقًا | ||
* يؤدي حذفه إلى إطلاق الخطأ ValueError | ** لن يعاد نتيجة لاستدعاء التابع <code>parser.popitem()</code> | ||
* لا يؤثر استدعاء التابع parser.clear() عليه إطلاقًا | |||
* لن | |||
* المعامل الثاني في التابع parser.get(section, option, **kwargs) لا يمثّل قيمة تراجعية fallback value. ولكن يجب الانتباه إلى أنّ توابع get() التي تعمل على مستوى القسم متوافقة مع بروتوكول الربط والواجهة البرمجية القديمة للوحدة configparser. | * المعامل الثاني في التابع <code>parser.get(section, option, **kwargs)</code> لا يمثّل قيمة تراجعية fallback value. ولكن يجب الانتباه إلى أنّ توابع <code>get()</code> التي تعمل على مستوى القسم متوافقة مع بروتوكول الربط والواجهة البرمجية القديمة للوحدة <code>configparser</code>. | ||
* التابع ()parser.items متوافق مع بروتوكول الربط (يعيد قائمة تحتوى على أزواج تتألف من (اسم القسم، وسيط القسم) section_name, section_proxy إضافة إلى DEFAULTSECT). ولكن يمكن تنفيذ هذا التابع باستخدام التوابع التالية: parser.items(section, raw, vars) | * التابع <code>()parser.items</code> متوافق مع بروتوكول الربط (يعيد قائمة تحتوى على أزواج تتألف من (اسم القسم، وسيط القسم) <code>section_name, section_proxy</code> إضافة إلى <code>DEFAULTSECT</code>). ولكن يمكن تنفيذ هذا التابع باستخدام التوابع التالية: <code>parser.items(section, raw, vars)</code>، وفي هذه الحالة سيعيد التابع قائمة تتضمّن أزواجًا تتألّف من (الخيار، القيمة) <code>option, value</code> للقسم المحدّد، مع توسيع جميع عمليات الاستيفاء (إلا إذا كان المعامل <code>raw</code> يحمل القيمة <code>True</code>). | ||
يأخذ بروتوكول الربط الأولوية على الواجهة البرمجية القديمة؛ ولهذا فإنّ الأصناف الفرعية التي تعيد تعريف الواجهة الأصلية ستمتلك روابط mappings تعمل كما هو متوقع منها. | يأخذ بروتوكول الربط الأولوية على الواجهة البرمجية القديمة؛ ولهذا فإنّ الأصناف الفرعية التي تعيد تعريف الواجهة الأصلية ستمتلك روابط mappings تعمل كما هو متوقع منها. | ||
تخصيص عمل المفسّر | == تخصيص عمل المفسّر == | ||
تتعدّد صيغ ملفات INI بتعدد التطبيقات التي تستخدم هذه الملفات، وتحاول وحدة <code>configparser</code> تقديم دعم جيّد لأكبر مجموعة من أنماط INI المتوفّرة حاليًّا. صمّمت طريقة عمل الوحدة بالاستناد إلى أنماط قديمة، ومن المرجّح أنّك سترغب في تخصيص بعض الميزات فيها. | |||
تتعدّد صيغ ملفات INI بتعدد التطبيقات التي تستخدم هذه الملفات، وتحاول وحدة configparser تقديم دعم جيّد لأكبر مجموعة من أنماط INI المتوفّرة حاليًّا. صمّمت طريقة عمل الوحدة بالاستناد إلى أنماط قديمة، ومن المرجّح أنّك سترغب في تخصيص بعض الميزات فيها. | |||
يمكن استخدام الخيارات المتاحة في التابع <code>__init__()</code> (وهي الطريقة الأكثر شيوعًا) لتغيير طريقة عمل مفسّر الإعدادات: | |||
* <code>defaults</code>, القيمة الافتراضية: <code>None</code> | |||
<blockquote>يستقبل هذا الخيار [[Python/dict|قاموسًا]] مكوّنًا من أزواج مفتاح-قيمة والتي ستُضاف في البداية إلى القسم <code>DEFAULT</code>. وتمثّل هذه الطريقة وسيلة جيّدة لدعم ملفات الإعدادات المختصرة والتي لا تحدّد قيمًا معيّنة، والتي تككون شبيهة بالإعدادات الافتراضية الموثّقة.</blockquote><blockquote>'''ملاحظة''': إن كنت ترغب في تحديد قيم افتراضية لقسم معيّن، استخدم التابع <code>read_dict()</code> قبل قراءة الملف الأصلي.</blockquote> | |||
* <code>dict_type</code>، القيمة الافتراضية: <code>[[Python/OrderedDict|collections.OrderedDict]]</code> | |||
<blockquote>يؤثّر هذا الخيار على طريقة عمل بروتوكول الربط وعلى طريقة كتابة ملف الإعدادات تأثيرًا كبيرًا؛ فعند استخدام القاموس المرتّب الافتراضي، يُخزّن كل قسم في ملف الإعدادات بنفس ترتيب إضافته إلى المفسّر، وينطبق الأمر نفسه على الخيارات التي تنطوي عليها الأقسام.</blockquote><blockquote>ويمكن استخدام نوع آخر من أنواع القواميس لترتيب الأقسام والخيارات -على سبيل المثال- عند إعادة كتابة ملف الإعدادات. كذلك يمكن استخدام قاموس عاديّ إن كان الأداء الجيّد أمرًا مطلوبًا.</blockquote><blockquote>'''ملاحظة''': هناك عدد من الطرق لإضافة مجموعة من أزواج مفتاح-قيمة بخطوة واحدة، وإن كنت تستخدم قاموسًا عاديًا في مثل هذه العمليات، فإنّ ترتيب المفاتيح سيكون عشوائيًا، إليك المثال التالي:</blockquote><syntaxhighlight lang="python3"> | |||
>>> parser = configparser.ConfigParser() | >>> parser = configparser.ConfigParser() | ||
>>> parser.read_dict({'section1': {'key1': 'value1', | >>> parser.read_dict({'section1': {'key1': 'value1', | ||
سطر 273: | سطر 261: | ||
>>> [option for option in parser['section3']] | >>> [option for option in parser['section3']] | ||
['baz', 'foo', 'bar'] | ['baz', 'foo', 'bar'] | ||
</syntaxhighlight>ستحتاج إلى استخدام قاموس مرتّب في هذه العمليات أيضًا:<syntaxhighlight lang="python3"> | |||
ستحتاج إلى استخدام قاموس مرتّب في هذه العمليات أيضًا: | |||
>>> from collections import OrderedDict | >>> from collections import OrderedDict | ||
>>> parser = configparser.ConfigParser() | >>> parser = configparser.ConfigParser() | ||
سطر 302: | سطر 288: | ||
>>> [option for option in parser['s2'].values()] | >>> [option for option in parser['s2'].values()] | ||
['b', 'd', 'f'] | ['b', 'd', 'f'] | ||
</syntaxhighlight> | |||
* <code>allow_no_value</code>, القيمة الافتراضية: <code>False</code> | |||
allow_no_value, القيمة الافتراضية: False | <blockquote>من المعروف أنّ بعض ملفات الإعدادات تتضمّن إعدادات خالية من القيم، ومع ذلك فإنّها متوافقة مع الصيغة التي تدعمها وحدة <code>configparser.</code></blockquote><blockquote>يمكن استخدام المعامل <code>allow_no_value</code> في الدالة البانية للسماح باستخدام مثل هذه القيم:</blockquote><syntaxhighlight lang="python3"> | ||
من المعروف أنّ بعض ملفات الإعدادات تتضمّن إعدادات خالية من القيم، ومع ذلك فإنّها متوافقة مع الصيغة التي تدعمها وحدة configparser. | |||
يمكن استخدام المعامل allow_no_value في الدالة البانية للسماح باستخدام مثل هذه القيم: | |||
>>> import configparser | >>> import configparser | ||
سطر 335: | سطر 318: | ||
... | ... | ||
KeyError: 'does-not-exist' | KeyError: 'does-not-exist' | ||
</syntaxhighlight> | |||
delimiters, القيمة الافتراضية: ('=', ':') | * <code>delimiters</code>, القيمة الافتراضية: (<code>'='</code>, <code>':'</code>) | ||
<blockquote>الفواصل عبارة عن [[Python/str|سلاسل نصية]] فرعية تفصل بين المفاتيح والقيم في القسم الواحد، ويعدّ أول ظهور للسلسلة النصية الفرعية الفاصلة في السطر على أنّه فاصل، وهذا يعني أنّ من الممكن أن تكون الفواصل موجودة في القيم ولكن ليس في المفاتيح. راجع المعامل <code>space_around_delimiters</code> في التابع <code>[[Python/ConfigParser/|ConfigParser.write()]]</code>.</blockquote> | |||
الفواصل عبارة عن سلاسل نصية فرعية تفصل بين المفاتيح والقيم في القسم الواحد، ويعدّ أول ظهور للسلسلة النصية الفرعية الفاصلة في السطر على أنّه فاصل، وهذا يعني أنّ من الممكن أن تكون الفواصل موجودة في القيم ولكن ليس في المفاتيح. | * <code>comment_prefixes</code>, القيمة الافتراضية: (<code>'#'</code> ، <code>';'</code>) | ||
راجع المعامل space_around_delimiters في التابع | * <code>inline_comment_prefixes</code>, القيمة الافتراضية: <code>None</code> | ||
<blockquote>سوابق التعليقات Comment prefixes هي سلاسل نصية تشير إلى بداية التعليق في ملف الإعدادات. تستخدم سوابق التعليقات في الأسطر الفارغة (والتي يمكن أن تكون مزاحة) أما سوابق التعليقات السطرية فيمكن استخدامها بعد أي قيمة صالحة (مثل: أسماء الأقسام، الخيارات والأسطر الفارغة أيضًا). تكون التعليقات السطرية معطّلة افتراضيًا، وتستخدم السابقتان <code>'#'</code> و <code>';'</code> مع التعليقات.</blockquote><blockquote>'''ملاحظة:''' في الإصدارات السابقة من الوحدة <code>configparser</code> كانت القيمة الافتراضية لسوابق التعليقات <code>comment_prefixes=('#', ';')</code> ولسوابق التعليقات السطرية <code>inline_comment_prefixes=(';',)</code>. هذا السلوك تغيّر في الإصدار 3.2 من بايثون.</blockquote><blockquote>يجب الانتباه إلى أنّه ليس بمقدور مفسّرات الإعدادات أن تهرّب المحارف المستخدمة كسوابق للتعليقات؛ ولهذا يمكن أن يمنع استخدام سوابق التعليقات السطرية المستخدمين من تحديد قيم للخيارات تتضمّن المحارف المستخدمة كسوابق للتعليقات؛ لذا ينصح بالامتناع عن تحديد أيّ قيمة لسوابق التعليقات السطرية.</blockquote><blockquote>في كثير من الأحيان تكون الطريقة الوحيدة لتخزين المحارف المستخدمة كسوابق للتعليقات في بداية السطر ضمن قيم متعددة الأسطر هي في استيفاء interpolate السابقة، فعلى سبيل المثال:</blockquote><syntaxhighlight lang="python3"> | |||
* comment_prefixes, القيمة الافتراضية: ('#' ، ';') | |||
* inline_comment_prefixes, القيمة الافتراضية: None | |||
سوابق التعليقات Comment prefixes هي سلاسل نصية تشير إلى بداية التعليق في ملف الإعدادات. تستخدم سوابق التعليقات في الأسطر الفارغة (والتي يمكن أن تكون مزاحة) أما سوابق التعليقات السطرية فيمكن استخدامها بعد أي قيمة صالحة (مثل: أسماء الأقسام، الخيارات والأسطر الفارغة أيضًا). تكون التعليقات السطرية معطّلة افتراضيًا، وتستخدم السابقتان '#' و ';' مع التعليقات. | |||
ملاحظة: في الإصدارات السابقة من الوحدة configparser كانت القيمة الافتراضية لسوابق التعليقات comment_prefixes=('#', ';') ولسوابق التعليقات السطرية inline_comment_prefixes=(';',). هذا السلوك تغيّر في الإصدار 3.2 من بايثون. | |||
يجب الانتباه إلى أنّه ليس بمقدور مفسّرات الإعدادات أن تهرّب المحارف المستخدمة كسوابق للتعليقات؛ ولهذا يمكن أن يمنع استخدام سوابق التعليقات السطرية المستخدمين من تحديد قيم للخيارات تتضمّن المحارف المستخدمة كسوابق للتعليقات؛ لذا ينصح بالامتناع عن تحديد أيّ قيمة لسوابق التعليقات السطرية. | |||
في كثير من الأحيان تكون الطريقة الوحيدة لتخزين المحارف المستخدمة كسوابق للتعليقات في بداية السطر ضمن قيم متعددة الأسطر هي في استيفاء interpolate السابقة، فعلى سبيل المثال: | |||
>>> from configparser import ConfigParser, ExtendedInterpolation | >>> from configparser import ConfigParser, ExtendedInterpolation | ||
>>> parser = ConfigParser(interpolation=ExtendedInterpolation()) | >>> parser = ConfigParser(interpolation=ExtendedInterpolation()) | ||
سطر 389: | سطر 362: | ||
line #2 | line #2 | ||
line #3 | line #3 | ||
</syntaxhighlight> | |||
* <code>strict</code>, القيمة الافتراضية: <code>True</code> | |||
strict, القيمة الافتراضية: True | <blockquote>إن أخذ هذا الخيار القيمة <code>True</code>، لن يسمح المفسّر بتكرار أيّ قسم أو خيار عند قراءة الإعدادات من مصدر واحد (باستخدام التوابع <code>[[Python/ConfigParser/read file|read_file()]]</code> أو <code>[[Python/ConfigParser/read string|read_string()]]</code> أو [[Python/ConfigParser/read dict|<code>read_dict()</code>]]). يُنصح باستخدام المفسّر في وضع التدقيق strict في التطبيقات الجديدة.</blockquote><blockquote>ملاحظة: كانت القيمة الافتراضية لهذا الخيار هي <code>False</code> في الإصدارات التي تسبق الإصدار 3.2 من بايثون.</blockquote> | ||
إن أخذ هذا الخيار القيمة | * <code>empty_lines_in_values</code>, القيمة الافتراضية: <code>True</code> | ||
<blockquote>يمكن للقيم في مفسّرات الإعدادات أن تمتدّ على أسطر متعددة ما دامات مزاحة عن المفتاح الذي يحمل تلك القيمة، وتسمح المفسّرات افتراضيًا بأن تكون الأسطر الفارغة جزءًا من القيم، كذلك يمكن إزاحة المفاتيح حسب الرغبة وذلك لزيادة مقروئية الملف، ولكن ارتفاع حجم الملف ودرجة تعقيد بنيته قد يؤديان إلى التسبب في ارتباك المستخدم عند التعامل مع الملف. إليك المثال التالي:</blockquote><syntaxhighlight lang="cfg"> | |||
ملاحظة: كانت القيمة الافتراضية لهذا الخيار هي False في الإصدارات التي تسبق الإصدار 3.2 من بايثون. | |||
empty_lines_in_values, | |||
يمكن للقيم في مفسّرات الإعدادات أن تمتدّ على أسطر متعددة ما دامات مزاحة عن المفتاح الذي يحمل تلك القيمة، وتسمح المفسّرات افتراضيًا بأن تكون الأسطر الفارغة جزءًا من القيم، كذلك يمكن إزاحة المفاتيح حسب الرغبة وذلك لزيادة مقروئية الملف، ولكن ارتفاع حجم الملف ودرجة تعقيد بنيته قد يؤديان إلى التسبب في ارتباك المستخدم عند التعامل مع الملف. إليك المثال التالي: | |||
[Section] | [Section] | ||
key = multiline | key = multiline | ||
سطر 405: | سطر 372: | ||
this = is still a part of the multiline value of 'key' | this = is still a part of the multiline value of 'key' | ||
</syntaxhighlight><blockquote>قد تتسبب بنية هذا الملف في حدوث مشاكل إن كان المستخدم يستعمل خطًا نسبيًا لتحرير الملف، وهذا هو السبب الذي يدعو إلى تعطيل الأسطر الفارغة إن كان التطبيق في غنى عنها؛ وبذلك تفصل الأسطر الفارغة بين المفاتيح دائمًا، وهكذا ينتج عن الملف في المثال السابق مفتاحان هما key و this.</blockquote> | |||
* <code>default_section</code>, القيمة الافتراضية: <code>configparser.DEFAULTSECT</code> (أي: <code>"DEFAULT"</code>) | |||
<blockquote>إن من أقوى الميّزات التي تقدّمها هذه المكتبة هي إمكانية استخدام قسم خاص بالقيم الافتراضية الخاصة بالأقسام الأخرى أو لأغراض الاستيفاء، وتسمح هذه الميزة للمستخدمين بإنشاء ملفات إعدادات معقّدة وواضحة في نفس الوقت. يدعى هذا القسم عادة بالاسم <code>"DEFAULT"</code> ولكن يمكن تخصيص ذلك للإشارة إلى اسم أي قسم آخر صالح للاستخدام، وعادة ما تستعمل الأسماء <code>"general"</code> أو <code>"common"</code>. يستخدم الاسم المقدّم لتمييز الأقسام الافتراضية عند قراءة الإعدادات من أي مصدر ويستخدم عند كتابة الإعدادات في ملف الإعدادات. يمكن الحصول على القيمة الحالية لهذا القسم عن طريق الخاصية <code>parser_instance.default_section</code> ويمكن تعديلها في وقت التشغيل (أي تحويل الملفات من صيغة إلى أخرى).</blockquote> | |||
* <code>interpolation</code>, القيمة الافتراضية: <code>configparser.BasicInterpolation</code> | |||
<blockquote>يمكن تخصيص طريقة استيفاء القيم عن طريق تقديم وسيلة خاصة في المعامل <code>interpolation</code>. يمكن استخدام القيمة <code>None</code> لإيقاف عملية الاستيفاء تمامًا، ويمكن استخدام القيمة <code>ExtendedInterpolation()</code> والتي تقدّم طريقة متقدّمة في استيفاء القيم مستوحاة من الحزمة [https://pypi.org/project/zc.buildout/ <code>zc.buildout</code>]. راجع قسم استيفاء القيم للاطلاع على المزيد من المعلومات. تمتلك كائنات <code>[[Python/RawConfigParser|RawConfigParser]]</code> القيمة الافتراضية <code>None</code>.</blockquote> | |||
* <code>converters</code>, القيمة الافتراضية: غير محددة | |||
<blockquote>تقدّم مفسّرات الإعدادات توابع مهمّتها جلب قيمة الخيار في ملف الإعدادات مع التحويل إلى الأنواع المناسبة، وتستخدم المفسّرات التوابع <code>[[Python/ConfigParser/getint|getint()]]</code> و <code>[[Python/ConfigParser/getfloat|getfloat()]]</code> و <code>[[Python/ConfigParser/getboolean|getboolean()]]</code> افتراضيًا. ويمكن للمستخدم إنشاء توابع خاصة حسب حاجته وذلك بتعريفها في صنف فرعي أو تمرير قاموس يكون كل مفتاح فيه هو اسم المحول وكلّ قيمة فيه هي كائنًا قابلًا للاستدعاء callable يطبّق عملية التحويل المطلوبة. فعلى سبيل المثال يؤدي تمرير القاموس <code>{'decimal':decimal.Decimal}</code> إلى إضافة التابع <code>getdecimal()</code> في كائن المفسّر وفي وسائط الأقسام section proxies كلّها. وبعبارة أخرى، سيكون بالإمكان استخدام التعبيرين <code>parser_instance.getdecimal('section','key', fallback=0)</code> و <code>parser_instance['section'].getdecimal('key', 0)</code>.</blockquote><blockquote>إن كان المحوّل بحاجة غلى الوصول إلى حالة المفسّر، فيمكن استخدامه حينئذ كتابع في صنف فرعي لمفسّر الإعدادات. إن كان اسم هذا التابع يبدأ بالكلمة get، فإنّه سيكون متوفّرًا في جميع وسائط الأقسام وبصيغة متوافقة مع القواميس (راجع المثال عن التابع <code>getdecimal()</code> في أعلاه).</blockquote><blockquote>يمكن زيادة التخصيص عن طريق إعادة تعريف القيم الافتراضية لخصائص المفسّر، وتعرّف القيم الافتراضية في الأصناف؛ ليكون بالإمكان إعادة تعريفها بواسطة الأصناف المتفرّعة عنها أو عن طريق إسناد القيم إلى خصائص الأصناف.</blockquote> | |||
=== <code>ConfigParser.BOOLEAN_STATES</code> === | |||
ينظر مفسّر الإعدادات -افتراضيًا- عند استخدامه للتابع<code>[[Python/ConfigParser/getboolean|getboolean()]]</code> إلى القيم: <code>'1'، 'yes'، 'true'، 'on'</code> على أنّها <code>True</code>، والقيم <code>'0'، 'no'، 'false'، 'off'</code> على أنّها <code>False</code>. يمكن إعادة تعريف ما سبق باستخدام قاموس مخصّص يتضمّن السلاسل النصية والقيم المنطقية الناتجة عنها، فعلى سبيل المثال: <syntaxhighlight lang="python3"> | |||
ConfigParser.BOOLEAN_STATES | |||
ينظر مفسّر الإعدادات -افتراضيًا- عند استخدامه للتابع getboolean() إلى القيم: '1'، 'yes'، 'true'، 'on' على أنّها | |||
>>> custom = configparser.ConfigParser() | >>> custom = configparser.ConfigParser() | ||
>>> custom['section1'] = {'funky': 'nope'} | >>> custom['section1'] = {'funky': 'nope'} | ||
سطر 434: | سطر 391: | ||
>>> custom['section1'].getboolean('funky') | >>> custom['section1'].getboolean('funky') | ||
False | False | ||
</syntaxhighlight>كذلك يمكن استخدام عبارات مثل <code>accept/reject</code> أو <code>enabled/disabled</code>. | |||
=== التابع <code>ConfigParser.optionxform(option)</code> === | |||
ConfigParser.optionxform(option) | |||
يحوّل التابع أسماء الخيارات في كل عمليّة قراءة أو جلب أو تعيين، ويحوّل الحروف في الأسماء -افتراضيًا- إلى حروف صغيرة؛ وهذا يعني كذلك أنّه عند كتابة ملفات الإعدادات فإنّ جميع المفاتيح ستكتب بحروف صغيرة. يمكن إعادة تعريف هذا التابع إن كانت طريقة عمله غير ملائمة. | يحوّل التابع أسماء الخيارات في كل عمليّة قراءة أو جلب أو تعيين، ويحوّل الحروف في الأسماء -افتراضيًا- إلى حروف صغيرة؛ وهذا يعني كذلك أنّه عند كتابة ملفات الإعدادات فإنّ جميع المفاتيح ستكتب بحروف صغيرة. يمكن إعادة تعريف هذا التابع إن كانت طريقة عمله غير ملائمة. | ||
مثال: | مثال:<syntaxhighlight lang="python3"> | ||
>>> config = """ | >>> config = """ | ||
... [Section1] | ... [Section1] | ||
سطر 464: | سطر 418: | ||
['AnotherKey'] | ['AnotherKey'] | ||
</syntaxhighlight> | |||
ConfigParser.SECTCRE | === <code>ConfigParser.SECTCRE</code> === | ||
تعبير نمطيّ مصرّف يستخدم لتفسير عناوين الأقسام. يطابق التعبير النمطي الافتراضي العبارة [section] مع الاسم "section". تعدّ المسافات البيضاء جزءًا من اسم القسم، ولهذا فإنّ التعبير [ larch ] سيُقرأ هكذا " larch ". | [[Python/re|تعبير نمطيّ]] مصرّف يستخدم لتفسير عناوين الأقسام. يطابق التعبير النمطي الافتراضي العبارة <code>[section]</code> مع الاسم <code>"section"</code>. تعدّ المسافات البيضاء جزءًا من اسم القسم، ولهذا فإنّ التعبير <code>[ larch ]</code> سيُقرأ هكذا <code>" larch "</code>. | ||
يمكن إعادة تعريف هذه الخاصية إن كانت طريقة عملها غير ملائمة. | يمكن إعادة تعريف هذه الخاصية إن كانت طريقة عملها غير ملائمة. | ||
مثال: | مثال:<syntaxhighlight lang="python3"> | ||
>>> import re | >>> import re | ||
>>> config = """ | >>> config = """ | ||
سطر 485: | سطر 439: | ||
['Section 1', ' Section 2 '] | ['Section 1', ' Section 2 '] | ||
>>> custom = configparser.ConfigParser() | >>> custom = configparser.ConfigParser() | ||
>>> custom.SECTCRE = re.compile(r"\[ *(?P | >>> custom.SECTCRE = re.compile(r"\[ *(?P<header>[^]]+?) *\]") | ||
>>> custom.read_string(config) | >>> custom.read_string(config) | ||
>>> custom.sections() | >>> custom.sections() | ||
['Section 1', 'Section 2'] | ['Section 1', 'Section 2'] | ||
</syntaxhighlight>'''ملاحظة:''' | |||
تستخدم كائنات <code>[[Python/ConfigParser|ConfigParser]]</code> الخاصية <code>OPTCRE</code> والتي تتعرّف على أسطر الخيارات، ولكن لا ينصح بإعادة تعريفها لأنّ ذلك قد يؤدي إلى حدوث تضارب مع خيار الدالة البانية <code>allow_no_value</code> ومع الفواصل <code>delimiters</code>. | |||
== أمثلة على الواجهة البرمجية القديمة == | |||
تقدّم وحدة configparser واجهة برمجية قديمة تتضمّن توابع get و set وذلك بهدف التوافق مع الإصدارات السابقة من اللغة. وعلى الرغم من وجود بعض الحالات التي يمكن استخدام التوابع المبيّنة أدناه فيها؛ يُنصح بالوصول إلى البيانات باستخدام بروتوكول الربط في المشاريع الجديدة. ويجدر التنبيه إلى أنّ الواجهة البرمجية القديمة قد تكون في بعض الأحيان أكثر تقدّمًا وذات مستوى أدنى وقد تكون في بعض الأحيان معاكسة للتوقعات. | |||
يبين المثال التالي طريقة كتابة ملف إعدادات:<syntaxhighlight lang="python3"> | |||
import configparser | |||
config = configparser.RawConfigParser() | |||
# يمكن استخدام دوال التعيين في كائنات RawConfigParser لتعيين قيم غير نصية | |||
# في المفاتيح داخليًا، ولكن تطلق اللغة خطأ عند محاولة الكتابة إلى ملفّ إعدادات | |||
# عند الوصول إليه في الوضع non-raw. لا تسمح عملية تعيين القيم باستخدام بروتوكول الربط أو التابع set() في كائنات ConfigParser بحدوث عمليات إسناد مماثلة. | |||
config.add_section('Section1') | |||
config.set('Section1', 'an_int', '15') | |||
config.set('Section1', 'a_bool', 'true') | |||
config.set('Section1', 'a_float', '3.1415') | |||
config.set('Section1', 'baz', 'fun') | |||
config.set('Section1', 'bar', 'Python') | |||
config.set('Section1', 'foo', '%(bar)s is %(baz)s!') | |||
# كتابة ملف الإعدادات إلى الملف 'example.cfg' | |||
with open('example.cfg', 'w') as configfile: | |||
config.write(configfile) | |||
</syntaxhighlight>يبين المثال التالي طريقة قراءة ملفّ الإعدادات مرة أخرى:<syntaxhighlight lang="python3"> | |||
import configparser | |||
config = configparser.RawConfigParser() | |||
config.read('example.cfg') | |||
# يطلق التابع getfloat() استثناءً إن لم تكن القيمة عددًا ذا فاصلة عائمة | |||
# وكذلك الأمر بالنسبة إلى التابعين getint() وgetboolean() مع الأنواع المقابلة لكل تابع. | |||
a_float = config.getfloat('Section1', 'a_float') | |||
an_int = config.getint('Section1', 'an_int') | |||
print(a_float + an_int) | |||
# لاحظ أنّ المخرجات التالية لا تستوفي '%(bar)s' أو '%(baz)s'. | |||
# وذلك لأنّنا نستخدم RawConfigParser(). | |||
if config.getboolean('Section1', 'a_bool'): | |||
print(config.get('Section1', 'foo')) | |||
</syntaxhighlight>يجب استخدام الكائن <code>[[Python/ConfigParser|ConfigParser]]</code> لإجراء عملية الاستيفاء:<syntaxhighlight lang="python3"> | |||
import configparser | |||
cfg = configparser.ConfigParser() | |||
cfg.read('example.cfg') | |||
# أسند القيمة True إلى المعامل *raw* في التابع get() إن كنت ترغب | |||
# في تعطيل عملية الاستيفاء في إحدى عمليات get. | |||
print(cfg.get('Section1', 'foo', raw=False)) # -> "Python is fun!" | |||
print(cfg.get('Section1', 'foo', raw=True)) # -> "%(bar)s is %(baz)s!" | |||
# المعامل الاختياري *vars* قاموس يتضمّن عناصر تأخذ | |||
# الأسبقية على عملية الاستيفاء. | |||
print(cfg.get('Section1', 'foo', vars={'bar': 'Documentation', | |||
'baz': 'evil'})) | |||
# يمكن استخدام المعامل الاختياري *fallback* لتوفير قيمة تراجعية | |||
print(cfg.get('Section1', 'foo')) | |||
# -> "Python is fun!" | |||
print(cfg.get('Section1', 'foo', fallback='Monty is not.')) | |||
# -> "Python is fun!" | |||
print(cfg.get('Section1', 'monster', fallback='No such things as monsters.')) | |||
# -> "No such things as monsters." | |||
# لا يمكن استخدام التعبير | |||
# print(cfg.get('Section1', 'monster')) | |||
# وذلك لأنّه سيتسبب في إطلاق الاستثناء NoOptionError، ولكن يمكن استخدام: | |||
print(cfg.get('Section1', 'monster', fallback=None)) | |||
# -> None | |||
</syntaxhighlight>القيم الافتراضية متوفّرة في كلا نوعي الكائن <code>[[Python/ConfigParser|ConfigParser]]</code>، وتستخدم هذه القيم في عملية الاستيفاء إن كان الخيار المستخدم غير معرّف في مكان آخر.<syntaxhighlight lang="python3"> | |||
import configparser | |||
# نسخة جديدة من الصنف مع تمرير القيم الافتراضية لكل خيار | |||
config = configparser.ConfigParser({'bar': 'Life', 'baz': 'hard'}) | |||
config.read('example.cfg') | |||
print(config.get('Section1', 'foo')) # -> "Python is fun!" | |||
config.remove_option('Section1', 'bar') | |||
config.remove_option('Section1', 'baz') | |||
print(config.get('Section1', 'foo')) # -> "Life is hard!" | |||
</syntaxhighlight> | |||
== كائنات <code>[[Python/ConfigParser|ConfigParser]]</code> == | |||
تعدّ هذه الكائنات المفسّر الرئيسي لملفات الإعدادات. | |||
== كائنات <code>[[Python/RawConfigParser|RawConfigParser]]</code> == | |||
هذه الكائنات هي النسخة القديمة من كائنات <code>[[Python/ConfigParser|ConfigParser]]</code>. | |||
== استثناءات الوحدة <code>configparser</code> == | |||
=== الاستثناء <code>configparser.Error</code> === | |||
الصنف الأساسي الذي تتفرّع منه بقية الاستثناءات في وحدة <code>configparser.</code> | |||
=== الاستثناء <code>configparser.NoSectionError</code> === | |||
يُطلق هذا الاستثناء عند عدم عثور المحلّل على قسم معيّن في ملف الإعدادات. | |||
=== الاستثناء <code>configparser.DuplicateSectionError</code> === | |||
يُطلق هذا الاستثناء إن استدعي التابع <code>add_section()</code> مع تمرير اسم لقسم موجودًا أصلًا في ملف الإعدادات، أو عند استخدام المحلّل في وضع التدقيق حين يعثر على قسمين يحملان الاسم ذاته في ملف أو سلسلة نصية أو قاموس واحد. | |||
ملاحظة: أضيفت الخصائص والمعاملات الاختيارية <code>source</code> و <code>lineno</code> إلى التابع <code>__init__()</code> في الإصدار 3.2 من بايثون. | |||
=== الاستثناء <code>configparser.DuplicateOptionError</code> === | |||
يطلق هذا الاستثناء بواسطة المحللّات التي تعمل في وضع التدقيق إن تكرر ظهور أحد الخيارات أثناء قراءة البيانات من ملف أو سلسلة نصية أو قاموس واحد. ويمكن لهذا الاستثناء أن يلتقط الأخطاء الإملائية في الأسماء إضافة إلى الأخطاء المتعلقة بحالة الأحرف، فعلى سبيل المثال يمكن لقاموس أن يمتلك مفتاحين يمثّلان نفس مفتاح الإعدادات الذي لا يكون حساسًا لحالة الأحرف. | |||
=== الاستثناء <code>configparser.NoOptionError</code> === | |||
يُطلق هذا الاستثناء عند عدم عثور المحلل على خيار معيّن في القسم المحدد. | |||
=== الاستثناء <code>configparser.InterpolationError</code> === | |||
الصنف الأساسي الذي تتفرّع منه الاستثناءات التي تُطلق عند حدوث مشاكل أثناء إجراء عملية استيفاء السلاسل النصية. | |||
=== الاستثناء <code>configparser.InterpolationDepthError</code> === | |||
يُطلق هذا الاستثناء عند عدم القدرة على إنهاء عملية استيفاء السلاسل النصية بسبب تجاوز عدد الدورات الحد الأقصى المعيّن في <code>MAX_INTERPOLATION_DEPTH</code>. يتفرّع هذا الصنف من الصنف <code>InterpolationError</code>. | |||
=== الاستثناء <code>configparser.InterpolationMissingOptionError</code> === | |||
يُطلق هذا الاستثناء عند غياب الخيار الذي تشير إليه قيمة معيّنة. يتفرّع هذا الصنف من الصنف <code>InterpolationError</code>. | |||
=== الاستثناء <code>configparser.InterpolationSyntaxError</code> === | |||
يُطلق هذا الاستثناء عندما يكون النص المصدري الذي تجري فيه عملية الاستبدال غير متوافق مع الصيغة المطلوبة. يتفرّع هذا الصنف من الصنف <code>InterpolationError</code>. | |||
=== الاستثناء <code>configparser.MissingSectionHeaderError</code> === | |||
يُطلق هذا الاستثناء عند محاولة المحلل تحليل ملف لا يمتلك ترويسات العناوين. | |||
=== الاستثناء <code>configparser.ParsingError</code> === | |||
يُطلق هذا الاستثناء عند حدوث أخطاء أثناء محاولة تحليل ملفّ معين. | |||
ملاحظة: تغير اسم الخاصية ومعامل التابع <code>__init__()</code> من <code>filname</code> إلى <code>tosource</code> في الإصدار 3.2 من بايثون. | |||
== مصادر == | |||
* [https://docs.python.org/3/library/configparser.html صفحة Configuration file parser في توثيق بايثون الرسمي.] | |||
[[تصنيف:Python]] | |||
[[تصنيف:Python/Modules]] |
المراجعة الحالية بتاريخ 07:23، 30 نوفمبر 2018
تقدّم هذه الوحدة الصنف ConfigParser
الذي يستخدم لغة إعدادات بسيطة تقدّم بنية مشابهة للبنية التي تقدّمها ملفات INI في نظام Microsoft Windows. ويمكن استخدام هذا الصنف لكتابة برامج وتطبيقات يمكن للمستخدمين تخصيصها بكل سهولة.
ملاحظة: لا تفسّر هذه المكتبة ولا تكتب لواحق قيمة-نوع التي يستخدمها إصدار سجلّ نظام ويندوز Windows Registry الموسّع بصيغة INI.
بداية سريعة
لنبدأ بملف الإعدادات البسيط التالي:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
يتكوّن الملف بصورة أساسية من أقسام sections ويتضمّن كل قسمٍ مفاتيح وقيم. يمكن للأصناف التي تقدّمها وحدة configparser
أن تقرأ وتكتب مثل هذه الملفات.
يمكن إنشاء محتويات ملف الإعدادات السابق برمجيًا باستخدام الشيفرة التالية:
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config['DEFAULT'] = {'ServerAliveInterval': '45',
... 'Compression': 'yes',
... 'CompressionLevel': '9'}
>>> config['bitbucket.org'] = {}
>>> config['bitbucket.org']['User'] = 'hg'
>>> config['topsecret.server.com'] = {}
>>> topsecret = config['topsecret.server.com']
>>> topsecret['Port'] = '50022' # تعديل المفسر
>>> topsecret['ForwardX11'] = 'no' # تعديل المفسر
>>> config['DEFAULT']['ForwardX11'] = 'yes'
>>> with open('example.ini', 'w') as configfile:
... config.write(configfile)
...
يبين المثال السابق أنّ التعامل مع مفسّر الإعدادات يشبه إلى حدٍّ كبير التعامل مع القواميس ولكن مع بعض الفروقات التي سيرد ذكرها لاحقًا. يمكن كذلك قراءة ملفات الإعدادات والاستفادة من محتوياتها كما يبيّن المثال التالي:
>>> config = configparser.ConfigParser()
>>> config.sections()
[]
>>> config.read('example.ini')
['example.ini']
>>> config.sections()
['bitbucket.org', 'topsecret.server.com']
>>> 'bitbucket.org' in config
True
>>> 'bytebong.com' in config
False
>>> config['bitbucket.org']['User']
'hg'
>>> config['DEFAULT']['Compression']
'yes'
>>> topsecret = config['topsecret.server.com']
>>> topsecret['ForwardX11']
'no'
>>> topsecret['Port']
'50022'
>>> for key in config['bitbucket.org']:
... print(key)
user
compressionlevel
serveraliveinterval
compression
forwardx11
>>> config['bitbucket.org']['ForwardX11']
'yes'
يقدّم القسم DEFAULT
القيم الافتراضية لجميع الأقسام، ويجب التنبيه هنا إلى أنّ أسماء المفاتيح في الأقسام غير حساسة لحالة الأحرف وتخزّن بالأحرف الصغيرة.
أنواع البيانات المدعومة
لا يستطيع مفسّر الإعدادات تخمين نوع البيانات في القيم المضمّنة في ملفات الإعدادات، ويخزّنها داخليًا كسلاسل نصيّة على الدوام، وهذا يعني وجوب تحويل البيانات إلى الأنواع المطلوبة يدويًا:
>>> int(topsecret['Port'])
50022
>>> float(topsecret['CompressionLevel'])
9.0
ولمّا كانت هذه العملية شائعة جدًّا، فإنّ مفسّر الإعدادات يقدّم مجموعة من توابع getter
للتعامل مع الأعداد الصحيحة، والأعداد ذات الفواصل العشرية، والقيم البوليانية والتي تمثّل المشكلة الأكبر ذلك لأنّه لا فائدة من استخدام الدالة bool()
لأنّ التعبير bool('False')
يعطي النتيجة True
دائمًا؛ ولهذا السبب يقدّم مفسّر الإعدادات التابع getboolean()
. هذا التابع غير حساس لحالة الأحرف ويمكنه التعرّف على القيم البوليانية من الكلمات 'yes'/'no'
، 'true'/'false'
، 'on'/'off'
و '1'/'0'
.
فعلى سبيل المثال:
>>> topsecret.getboolean('ForwardX11')
False
>>> config['bitbucket.org'].getboolean('ForwardX11')
True
>>> config.getboolean('bitbucket.org', 'Compression')
True
يقدّم مفسّر الإعدادات كذلك التابعين getint()
و getfloat()
، ويمكن إلى جانب ما سبق تسجيل محوّلات خاصة بالمستخدم وتخصيص المحوّلات الموجودة أيضًا.
القيم التراجعية Fallback Values
كما هو الحال مع القواميس يمكن استخدام التابع get()
الخاص بقسم معين لتقديم قيم تراجعية:
>>> topsecret.get('Port')
'50022'
>>> topsecret.get('CompressionLevel')
'9'
>>> topsecret.get('Cipher')
>>> topsecret.get('Cipher', '3des-cbc')
'3des-cbc'
ولكن يجب الانتباه إلى أنّ القيم الافتراضية تمتلك الأسبقية على القيم التراجعية، ففي المثال السابق جرى تعيين المفتاح 'CompressionLevel'
في القسم 'DEFAULT'
فقط، وإن حاولنا الحصول على قيمته من القسم 'topsecret.server.com'
فسنحصل دائمًا على القيم الافتراضية، حتى لو جرى تحديد قيمته التراجعية:
>>> topsecret.get('CompressionLevel', '3')
'9'
كذلك يجب التنبيه إلى أنّ التابع get()
الذي يعمل على مستوى المفسّر يقدّم واجهة مخصّصة وأكثر تعقيدًا، وهي متوافقة مع الإصدارات السابقة. عند استخدام هذا التابع يمكن تقديم قيمة تراجعية باستخدام المعامل المفتاحي fallback
:
>>> config.get('bitbucket.org', 'monster',
... fallback='No such things as monsters')
'No such things as monsters'
يمكن استخدام المعامل fallback
مع التوابع getint()
و getfloat()
و getboolean()
، فعلى سبيل المثال:
>>> 'BatchMode' in topsecret
False
>>> topsecret.getboolean('BatchMode', fallback=True)
True
>>> config['DEFAULT']['BatchMode'] = 'no'
>>> topsecret.getboolean('BatchMode', fallback=True)
False
بنية ملفات INI المدعومة
يتكوّن ملف الإعدادات من أقسام، ويبدأ كل قسم منها بترويسة تحمل اسم القسم [section]
متبوعةً بعدد من المدخلات على هيئة مفتاح/قيمة، وتفصل سلسلة نصية معينة بين المفتاح والقيمة (=
أو :
افتراضيًا). تكون أسماء الأقسام غير حساسة لحالة الأحرف افتراضيًا، أمّا المفاتيح فلا، وتُحذف جميع المسافات البيضاء من بداية ونهاية المفاتيح والقيم. يمكن الاستغناء عن القيم، وفي هذه الحالة يمكن الاستغناء أيضًا عن الفاصل بين المفتاح والقيمة. ويمكن للقيم أن تمتدّ على أسطر متعددة، ما دامت مزاحة عن السطر الأول من القيمة. يمكن أن يتعامل مفسّر الإعدادات مع الأسطر الفارغة كجزء من قيم متعددة الأسطر أو يمكنه أن يتجاهلها، وكلّ ذلك بالاعتماد على وضع المفسّر المستخدم.
يمكن أن تتضمّن ملفات الإعدادات التعليقات، وتكون مسبوقة بمحارف محددة (#
و ;
افتراضيًا)، وتظهر في سطر منفرد وتكون قابلة للإزاحة.
فعلى سبيل المثال:
[Simple Values]
key=value
spaces in keys=allowed
spaces in values=allowed as well
spaces around the delimiter = obviously
you can also use : to delimit keys from values
[All Values Are Strings]
values like this: 1000000
or this: 3.14159265359
are they treated as numbers? : no
integers, floats and booleans are held as: strings
can use the API to get converted values directly: true
[Multiline Values]
chorus: I'm a lumberjack, and I'm okay
I sleep all night and I work all day
[No Values]
key_without_value
empty string value here =
[You can use comments]
# like this
; or this
# By default only in an empty line.
# Inline comments can be harmful because they prevent users
# from using the delimiting characters as parts of values.
# That being said, this can be customized.
[Sections Can Be Indented]
can_values_be_as_well = True
does_that_mean_anything_special = False
purpose = formatting for readability
multiline_values = are
handled just fine as
long as they are indented
deeper than the first line
of a value
# Did I mention we can indent comments, too?
استيفاء القيم Interpolation of values
يدعم الصنف ConfigParser
استيفاء القيم، ما يعني إمكانية معالجة القيم قبل إعادتها من استدعاءات التابع get()
.
الصنف configparser.BasicInterpolation
هذا الصنف هو الطريقة الافتراضية التي يستخدمها الصنف ConfigParser
لاستيفاء القيم. يتيح هذا الصنف استخدام سلاسل تنسيق نصية في قيم ملف الإعدادات وتشير سلاسل التنسيق هذه إلى قيم اخرى في القسم نفسه، أو إلى قيم في قسم DEFAULT
الخاص، ويمكن تقديم قيم افتراضية إضافية عند تهيئة الملف.
فعلى سبيل المثال:
[Paths]
home_dir: /Users
my_dir: %(home_dir)s/lumberjack
my_pictures: %(my_dir)s/Pictures
إن أخذ المعامل interpolation
في الدالة البانية للصنف ConfigParser
القيمة BasicInterpolation()
فإنّ الصنف ConfigParser
سيحلّل %(home_dir)s
إلى القيمة home_dir
(وهو المجلد /Users
في هذه الحالة)، وسيحلّل %(my_dir)s
إلى /Users/lumberjack
.
من الجدير بالذكر أنّ عمليات الاستيفاء كلها تجري حسب الطلب؛ لهذا لا حاجة إلى استخدام ترتيب معيّن للمفاتيح في ملف الإعدادات عند استخدامها في إشارات مترابطة.
في حال تعيين القيمة None
للمعامل interpolation
في الدالة البانية للصنف ConfigParser
، فإنّ الصنف سيعيد العبارة %(home_dir)s/Pictures
كقيمة للمفتاح my_pictures
والعبارة %(home_dir)s/lumberjack
كقيمة للمفتاح my_dir
.
الصنف configparser.ExtendedInterpolation
طريقة أخرى لاستيفاء القيم وتستخدم صيغة أكثر تقدّمًا، وتستخدم في حزمة zc.buildout على سبيل المثال. يُقصد بالاستيفاء الموسّع Extended interpolation استخدام الصيغة ${section:option}
للإشارة إلى قيمة في قسم آخر. يمكن للاستيفاء أن يمتد لمستويات متعددة، وإن حذف الجزء section
: من الصيغة فإنّ عملية الاستيفاء تكون ضمن القسم الحالي افتراضيًا (ومن المحتمل أن تُستوفى القيم الافتراضية من القسم الخاص).
فعلى سبيل المثال، ستظهر الإعدادات التي مرّ ذكرها في قسم الاستيفاء العادي بالمظهر التالي في الاستيفاء الموسّع:
[Paths]
home_dir: /Users
my_dir: ${home_dir}/lumberjack
my_pictures: ${my_dir}/Pictures
يمكن جلب قيم من أقسام أخرى أيضًا:
[Common]
home_dir: /Users
library_dir: /Library
system_dir: /System
macports_dir: /opt/local
[Frameworks]
Python: 3.2
path: ${Common:system_dir}/Library/Frameworks/
[Arthur]
nickname: Two Sheds
last_name: Jackson
my_dir: ${Common:home_dir}/twosheds
my_pictures: ${my_dir}/Pictures
python_dir: ${Frameworks:path}/Python/Versions/${Frameworks:Python}
الوصول إلى القيم باستخدام بروتوكول الربط Mapping Protocol
ملاحظة: هذا البروتوكول جديد في الإصدار 3.2 من بايثون.
يُطلق هذا الاسم على الوظيفة التي تتيح استخدام كائنات خاصة كما لو أنّها كانت قواميس. وتُستخدم الصيغة parser['section']['option']
كواجهة للربط في وحدة configparser
.
يعيد الجزء parser['section']
وسيطًا proxy لبيانات القسم في المحلل، وهذا يعني أنّ القيم لا تنسخ ولكنّها تُؤخذ من المفسّر الأصلي عند الحاجة. ويجب التنبيه إلى أنّه عند تغيير القيم في وسيط القسم فإنّ ما يجري في الواقع هو تعديل القيم في المفسّر الأصلي.
تسلك كائنات الوحدة configparser
سلوكًا مقاربًا للقواميس إلى حدٍّ كبير، وواجهة الربط كاملة وتلتزم بما يفرضه الصنف MutableMapping ABC
، ولكن هناك بعض الاختلافات التي يجب أخذها بالحسبان:
- جميع المفاتيح في الأقسام غير حساسة لحالة الأحرف، فعلى سبيل المثال يعيد التعبير:
for option in parser["section"]
يعيد أسماء المفاتيح التي المحوّلة بواسطة التابع optionxform()
، أي أنّ المفاتيح تكون بالحرف الصغير افتراضيًا، وفي نفس الوقت، يعطي التعبيران التاليان النتيجة True
لقسم يتضمّن المفتاحين:
"a" in parser["section"]
"A" in parser["section"]
- تتضمّن جميع الأقسام كذلك قيم
DEFAULTSECT
، وهذا يعني أنّ القسم لن يبدو فارغًا إن استدعي التابع clear() على ذلك القسم؛ وذلك لعدم إمكانية حذف القيم الافتراضية من القسم (لأنّها ليست موجودة فيه أصلًا)، وإن كان القسم يعيد تعريف القيم الافتراضية، فإنّ حذف القيم الجديدة في القسم سيتسبب في إعادة إظهار القيم الافتراضية. يؤدي حذف أيّ قيمة افتراضية إلى إطلاق الخطأKeyError
.
- لا يمكن حذف
DEFAULTSECT
من المفسّر:- يؤدي حذفه إلى إطلاق الخطأ
ValueError
- لا يؤثر استدعاء التابع
parser.clear()
عليه إطلاقًا - لن يعاد نتيجة لاستدعاء التابع
parser.popitem()
- يؤدي حذفه إلى إطلاق الخطأ
- المعامل الثاني في التابع
parser.get(section, option, **kwargs)
لا يمثّل قيمة تراجعية fallback value. ولكن يجب الانتباه إلى أنّ توابعget()
التي تعمل على مستوى القسم متوافقة مع بروتوكول الربط والواجهة البرمجية القديمة للوحدةconfigparser
.
- التابع
()parser.items
متوافق مع بروتوكول الربط (يعيد قائمة تحتوى على أزواج تتألف من (اسم القسم، وسيط القسم)section_name, section_proxy
إضافة إلىDEFAULTSECT
). ولكن يمكن تنفيذ هذا التابع باستخدام التوابع التالية:parser.items(section, raw, vars)
، وفي هذه الحالة سيعيد التابع قائمة تتضمّن أزواجًا تتألّف من (الخيار، القيمة)option, value
للقسم المحدّد، مع توسيع جميع عمليات الاستيفاء (إلا إذا كان المعاملraw
يحمل القيمةTrue
).
يأخذ بروتوكول الربط الأولوية على الواجهة البرمجية القديمة؛ ولهذا فإنّ الأصناف الفرعية التي تعيد تعريف الواجهة الأصلية ستمتلك روابط mappings تعمل كما هو متوقع منها.
تخصيص عمل المفسّر
تتعدّد صيغ ملفات INI بتعدد التطبيقات التي تستخدم هذه الملفات، وتحاول وحدة configparser
تقديم دعم جيّد لأكبر مجموعة من أنماط INI المتوفّرة حاليًّا. صمّمت طريقة عمل الوحدة بالاستناد إلى أنماط قديمة، ومن المرجّح أنّك سترغب في تخصيص بعض الميزات فيها.
يمكن استخدام الخيارات المتاحة في التابع __init__()
(وهي الطريقة الأكثر شيوعًا) لتغيير طريقة عمل مفسّر الإعدادات:
defaults
, القيمة الافتراضية:None
يستقبل هذا الخيار قاموسًا مكوّنًا من أزواج مفتاح-قيمة والتي ستُضاف في البداية إلى القسم
DEFAULT
. وتمثّل هذه الطريقة وسيلة جيّدة لدعم ملفات الإعدادات المختصرة والتي لا تحدّد قيمًا معيّنة، والتي تككون شبيهة بالإعدادات الافتراضية الموثّقة.
ملاحظة: إن كنت ترغب في تحديد قيم افتراضية لقسم معيّن، استخدم التابع
read_dict()
قبل قراءة الملف الأصلي.
dict_type
، القيمة الافتراضية:collections.OrderedDict
يؤثّر هذا الخيار على طريقة عمل بروتوكول الربط وعلى طريقة كتابة ملف الإعدادات تأثيرًا كبيرًا؛ فعند استخدام القاموس المرتّب الافتراضي، يُخزّن كل قسم في ملف الإعدادات بنفس ترتيب إضافته إلى المفسّر، وينطبق الأمر نفسه على الخيارات التي تنطوي عليها الأقسام.
ويمكن استخدام نوع آخر من أنواع القواميس لترتيب الأقسام والخيارات -على سبيل المثال- عند إعادة كتابة ملف الإعدادات. كذلك يمكن استخدام قاموس عاديّ إن كان الأداء الجيّد أمرًا مطلوبًا.
ملاحظة: هناك عدد من الطرق لإضافة مجموعة من أزواج مفتاح-قيمة بخطوة واحدة، وإن كنت تستخدم قاموسًا عاديًا في مثل هذه العمليات، فإنّ ترتيب المفاتيح سيكون عشوائيًا، إليك المثال التالي:
>>> parser = configparser.ConfigParser()
>>> parser.read_dict({'section1': {'key1': 'value1',
... 'key2': 'value2',
... 'key3': 'value3'},
... 'section2': {'keyA': 'valueA',
... 'keyB': 'valueB',
... 'keyC': 'valueC'},
... 'section3': {'foo': 'x',
... 'bar': 'y',
... 'baz': 'z'}
... })
>>> parser.sections()
['section3', 'section2', 'section1']
>>> [option for option in parser['section3']]
['baz', 'foo', 'bar']
ستحتاج إلى استخدام قاموس مرتّب في هذه العمليات أيضًا:
>>> from collections import OrderedDict
>>> parser = configparser.ConfigParser()
>>> parser.read_dict(
... OrderedDict((
... ('s1',
... OrderedDict((
... ('1', '2'),
... ('3', '4'),
... ('5', '6'),
... ))
... ),
... ('s2',
... OrderedDict((
... ('a', 'b'),
... ('c', 'd'),
... ('e', 'f'),
... ))
... ),
... ))
... )
>>> parser.sections()
['s1', 's2']
>>> [option for option in parser['s1']]
['1', '3', '5']
>>> [option for option in parser['s2'].values()]
['b', 'd', 'f']
allow_no_value
, القيمة الافتراضية:False
من المعروف أنّ بعض ملفات الإعدادات تتضمّن إعدادات خالية من القيم، ومع ذلك فإنّها متوافقة مع الصيغة التي تدعمها وحدة
configparser.
يمكن استخدام المعامل
allow_no_value
في الدالة البانية للسماح باستخدام مثل هذه القيم:
>>> import configparser
>>> sample_config = """
... [mysqld]
... user = mysql
... pid-file = /var/run/mysqld/mysqld.pid
... skip-external-locking
... old_passwords = 1
... skip-bdb
... # we don't need ACID today
... skip-innodb
... """
>>> config = configparser.ConfigParser(allow_no_value=True)
>>> config.read_string(sample_config)
>>> # يجري التعامل مع الإعدادات ذات القيم بالطريقة المعتادة:
>>> config["mysqld"]["user"]
'mysql'
>>> # الإعدادات الخالية من القيم تقدّم القيمة None:
>>> config["mysqld"]["skip-bdb"]
>>> # ما زالت الإعدادات غير الموجودة تطلق أخطاءً:
>>> config["mysqld"]["does-not-exist"]
Traceback (most recent call last):
...
KeyError: 'does-not-exist'
delimiters
, القيمة الافتراضية: ('='
,':'
)
الفواصل عبارة عن سلاسل نصية فرعية تفصل بين المفاتيح والقيم في القسم الواحد، ويعدّ أول ظهور للسلسلة النصية الفرعية الفاصلة في السطر على أنّه فاصل، وهذا يعني أنّ من الممكن أن تكون الفواصل موجودة في القيم ولكن ليس في المفاتيح. راجع المعامل
space_around_delimiters
في التابعConfigParser.write()
.
comment_prefixes
, القيمة الافتراضية: ('#'
،';'
)inline_comment_prefixes
, القيمة الافتراضية:None
سوابق التعليقات Comment prefixes هي سلاسل نصية تشير إلى بداية التعليق في ملف الإعدادات. تستخدم سوابق التعليقات في الأسطر الفارغة (والتي يمكن أن تكون مزاحة) أما سوابق التعليقات السطرية فيمكن استخدامها بعد أي قيمة صالحة (مثل: أسماء الأقسام، الخيارات والأسطر الفارغة أيضًا). تكون التعليقات السطرية معطّلة افتراضيًا، وتستخدم السابقتان
'#'
و';'
مع التعليقات.
ملاحظة: في الإصدارات السابقة من الوحدة
configparser
كانت القيمة الافتراضية لسوابق التعليقاتcomment_prefixes=('#', ';')
ولسوابق التعليقات السطريةinline_comment_prefixes=(';',)
. هذا السلوك تغيّر في الإصدار 3.2 من بايثون.
يجب الانتباه إلى أنّه ليس بمقدور مفسّرات الإعدادات أن تهرّب المحارف المستخدمة كسوابق للتعليقات؛ ولهذا يمكن أن يمنع استخدام سوابق التعليقات السطرية المستخدمين من تحديد قيم للخيارات تتضمّن المحارف المستخدمة كسوابق للتعليقات؛ لذا ينصح بالامتناع عن تحديد أيّ قيمة لسوابق التعليقات السطرية.
في كثير من الأحيان تكون الطريقة الوحيدة لتخزين المحارف المستخدمة كسوابق للتعليقات في بداية السطر ضمن قيم متعددة الأسطر هي في استيفاء interpolate السابقة، فعلى سبيل المثال:
>>> from configparser import ConfigParser, ExtendedInterpolation
>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
>>> # the default BasicInterpolation could be used as well
>>> parser.read_string("""
... [DEFAULT]
... hash = #
...
... [hashes]
... shebang =
... ${hash}!/usr/bin/env python
... ${hash} -*- coding: utf-8 -*-
...
... extensions =
... enabled_extension
... another_extension
... #disabled_by_comment
... yet_another_extension
...
... interpolation not necessary = if # is not at line start
... even in multiline values = line #1
... line #2
... line #3
... """)
>>> print(parser['hashes']['shebang'])
#!/usr/bin/env python
# -*- coding: utf-8 -*-
>>> print(parser['hashes']['extensions'])
enabled_extension
another_extension
yet_another_extension
>>> print(parser['hashes']['interpolation not necessary'])
if # is not at line start
>>> print(parser['hashes']['even in multiline values'])
line #1
line #2
line #3
strict
, القيمة الافتراضية:True
إن أخذ هذا الخيار القيمة
True
، لن يسمح المفسّر بتكرار أيّ قسم أو خيار عند قراءة الإعدادات من مصدر واحد (باستخدام التوابعread_file()
أوread_string()
أوread_dict()
). يُنصح باستخدام المفسّر في وضع التدقيق strict في التطبيقات الجديدة.
ملاحظة: كانت القيمة الافتراضية لهذا الخيار هي
False
في الإصدارات التي تسبق الإصدار 3.2 من بايثون.
empty_lines_in_values
, القيمة الافتراضية:True
يمكن للقيم في مفسّرات الإعدادات أن تمتدّ على أسطر متعددة ما دامات مزاحة عن المفتاح الذي يحمل تلك القيمة، وتسمح المفسّرات افتراضيًا بأن تكون الأسطر الفارغة جزءًا من القيم، كذلك يمكن إزاحة المفاتيح حسب الرغبة وذلك لزيادة مقروئية الملف، ولكن ارتفاع حجم الملف ودرجة تعقيد بنيته قد يؤديان إلى التسبب في ارتباك المستخدم عند التعامل مع الملف. إليك المثال التالي:
[Section]
key = multiline
value with a gotcha
this = is still a part of the multiline value of 'key'
قد تتسبب بنية هذا الملف في حدوث مشاكل إن كان المستخدم يستعمل خطًا نسبيًا لتحرير الملف، وهذا هو السبب الذي يدعو إلى تعطيل الأسطر الفارغة إن كان التطبيق في غنى عنها؛ وبذلك تفصل الأسطر الفارغة بين المفاتيح دائمًا، وهكذا ينتج عن الملف في المثال السابق مفتاحان هما key و this.
default_section
, القيمة الافتراضية:configparser.DEFAULTSECT
(أي:"DEFAULT"
)
إن من أقوى الميّزات التي تقدّمها هذه المكتبة هي إمكانية استخدام قسم خاص بالقيم الافتراضية الخاصة بالأقسام الأخرى أو لأغراض الاستيفاء، وتسمح هذه الميزة للمستخدمين بإنشاء ملفات إعدادات معقّدة وواضحة في نفس الوقت. يدعى هذا القسم عادة بالاسم
"DEFAULT"
ولكن يمكن تخصيص ذلك للإشارة إلى اسم أي قسم آخر صالح للاستخدام، وعادة ما تستعمل الأسماء"general"
أو"common"
. يستخدم الاسم المقدّم لتمييز الأقسام الافتراضية عند قراءة الإعدادات من أي مصدر ويستخدم عند كتابة الإعدادات في ملف الإعدادات. يمكن الحصول على القيمة الحالية لهذا القسم عن طريق الخاصيةparser_instance.default_section
ويمكن تعديلها في وقت التشغيل (أي تحويل الملفات من صيغة إلى أخرى).
interpolation
, القيمة الافتراضية:configparser.BasicInterpolation
يمكن تخصيص طريقة استيفاء القيم عن طريق تقديم وسيلة خاصة في المعامل
interpolation
. يمكن استخدام القيمةNone
لإيقاف عملية الاستيفاء تمامًا، ويمكن استخدام القيمةExtendedInterpolation()
والتي تقدّم طريقة متقدّمة في استيفاء القيم مستوحاة من الحزمةzc.buildout
. راجع قسم استيفاء القيم للاطلاع على المزيد من المعلومات. تمتلك كائناتRawConfigParser
القيمة الافتراضيةNone
.
converters
, القيمة الافتراضية: غير محددة
تقدّم مفسّرات الإعدادات توابع مهمّتها جلب قيمة الخيار في ملف الإعدادات مع التحويل إلى الأنواع المناسبة، وتستخدم المفسّرات التوابع
getint()
وgetfloat()
وgetboolean()
افتراضيًا. ويمكن للمستخدم إنشاء توابع خاصة حسب حاجته وذلك بتعريفها في صنف فرعي أو تمرير قاموس يكون كل مفتاح فيه هو اسم المحول وكلّ قيمة فيه هي كائنًا قابلًا للاستدعاء callable يطبّق عملية التحويل المطلوبة. فعلى سبيل المثال يؤدي تمرير القاموس{'decimal':decimal.Decimal}
إلى إضافة التابعgetdecimal()
في كائن المفسّر وفي وسائط الأقسام section proxies كلّها. وبعبارة أخرى، سيكون بالإمكان استخدام التعبيرين parser_instance.getdecimal('section','key', fallback=0)
و parser_instance['section'].getdecimal('key', 0)
.
إن كان المحوّل بحاجة غلى الوصول إلى حالة المفسّر، فيمكن استخدامه حينئذ كتابع في صنف فرعي لمفسّر الإعدادات. إن كان اسم هذا التابع يبدأ بالكلمة get، فإنّه سيكون متوفّرًا في جميع وسائط الأقسام وبصيغة متوافقة مع القواميس (راجع المثال عن التابع
getdecimal()
في أعلاه).
يمكن زيادة التخصيص عن طريق إعادة تعريف القيم الافتراضية لخصائص المفسّر، وتعرّف القيم الافتراضية في الأصناف؛ ليكون بالإمكان إعادة تعريفها بواسطة الأصناف المتفرّعة عنها أو عن طريق إسناد القيم إلى خصائص الأصناف.
ConfigParser.BOOLEAN_STATES
ينظر مفسّر الإعدادات -افتراضيًا- عند استخدامه للتابعgetboolean()
إلى القيم: '1'، 'yes'، 'true'، 'on'
على أنّها True
، والقيم '0'، 'no'، 'false'، 'off'
على أنّها False
. يمكن إعادة تعريف ما سبق باستخدام قاموس مخصّص يتضمّن السلاسل النصية والقيم المنطقية الناتجة عنها، فعلى سبيل المثال:
>>> custom = configparser.ConfigParser()
>>> custom['section1'] = {'funky': 'nope'}
>>> custom['section1'].getboolean('funky')
Traceback (most recent call last):
...
ValueError: Not a boolean: nope
>>> custom.BOOLEAN_STATES = {'sure': True, 'nope': False}
>>> custom['section1'].getboolean('funky')
False
كذلك يمكن استخدام عبارات مثل accept/reject
أو enabled/disabled
.
التابع ConfigParser.optionxform(option)
يحوّل التابع أسماء الخيارات في كل عمليّة قراءة أو جلب أو تعيين، ويحوّل الحروف في الأسماء -افتراضيًا- إلى حروف صغيرة؛ وهذا يعني كذلك أنّه عند كتابة ملفات الإعدادات فإنّ جميع المفاتيح ستكتب بحروف صغيرة. يمكن إعادة تعريف هذا التابع إن كانت طريقة عمله غير ملائمة.
مثال:
>>> config = """
... [Section1]
... Key = Value
...
... [Section2]
... AnotherKey = Value
... """
>>> typical = configparser.ConfigParser()
>>> typical.read_string(config)
>>> list(typical['Section1'].keys())
['key']
>>> list(typical['Section2'].keys())
['anotherkey']
>>> custom = configparser.RawConfigParser()
>>> custom.optionxform = lambda option: option
>>> custom.read_string(config)
>>> list(custom['Section1'].keys())
['Key']
>>> list(custom['Section2'].keys())
['AnotherKey']
ConfigParser.SECTCRE
تعبير نمطيّ مصرّف يستخدم لتفسير عناوين الأقسام. يطابق التعبير النمطي الافتراضي العبارة [section]
مع الاسم "section"
. تعدّ المسافات البيضاء جزءًا من اسم القسم، ولهذا فإنّ التعبير [ larch ]
سيُقرأ هكذا " larch "
.
يمكن إعادة تعريف هذه الخاصية إن كانت طريقة عملها غير ملائمة.
مثال:
>>> import re
>>> config = """
... [Section 1]
... option = value
...
... [ Section 2 ]
... another = val
... """
>>> typical = configparser.ConfigParser()
>>> typical.read_string(config)
>>> typical.sections()
['Section 1', ' Section 2 ']
>>> custom = configparser.ConfigParser()
>>> custom.SECTCRE = re.compile(r"\[ *(?P<header>[^]]+?) *\]")
>>> custom.read_string(config)
>>> custom.sections()
['Section 1', 'Section 2']
ملاحظة:
تستخدم كائنات ConfigParser
الخاصية OPTCRE
والتي تتعرّف على أسطر الخيارات، ولكن لا ينصح بإعادة تعريفها لأنّ ذلك قد يؤدي إلى حدوث تضارب مع خيار الدالة البانية allow_no_value
ومع الفواصل delimiters
.
أمثلة على الواجهة البرمجية القديمة
تقدّم وحدة configparser واجهة برمجية قديمة تتضمّن توابع get و set وذلك بهدف التوافق مع الإصدارات السابقة من اللغة. وعلى الرغم من وجود بعض الحالات التي يمكن استخدام التوابع المبيّنة أدناه فيها؛ يُنصح بالوصول إلى البيانات باستخدام بروتوكول الربط في المشاريع الجديدة. ويجدر التنبيه إلى أنّ الواجهة البرمجية القديمة قد تكون في بعض الأحيان أكثر تقدّمًا وذات مستوى أدنى وقد تكون في بعض الأحيان معاكسة للتوقعات.
يبين المثال التالي طريقة كتابة ملف إعدادات:
import configparser
config = configparser.RawConfigParser()
# يمكن استخدام دوال التعيين في كائنات RawConfigParser لتعيين قيم غير نصية
# في المفاتيح داخليًا، ولكن تطلق اللغة خطأ عند محاولة الكتابة إلى ملفّ إعدادات
# عند الوصول إليه في الوضع non-raw. لا تسمح عملية تعيين القيم باستخدام بروتوكول الربط أو التابع set() في كائنات ConfigParser بحدوث عمليات إسناد مماثلة.
config.add_section('Section1')
config.set('Section1', 'an_int', '15')
config.set('Section1', 'a_bool', 'true')
config.set('Section1', 'a_float', '3.1415')
config.set('Section1', 'baz', 'fun')
config.set('Section1', 'bar', 'Python')
config.set('Section1', 'foo', '%(bar)s is %(baz)s!')
# كتابة ملف الإعدادات إلى الملف 'example.cfg'
with open('example.cfg', 'w') as configfile:
config.write(configfile)
يبين المثال التالي طريقة قراءة ملفّ الإعدادات مرة أخرى:
import configparser
config = configparser.RawConfigParser()
config.read('example.cfg')
# يطلق التابع getfloat() استثناءً إن لم تكن القيمة عددًا ذا فاصلة عائمة
# وكذلك الأمر بالنسبة إلى التابعين getint() وgetboolean() مع الأنواع المقابلة لكل تابع.
a_float = config.getfloat('Section1', 'a_float')
an_int = config.getint('Section1', 'an_int')
print(a_float + an_int)
# لاحظ أنّ المخرجات التالية لا تستوفي '%(bar)s' أو '%(baz)s'.
# وذلك لأنّنا نستخدم RawConfigParser().
if config.getboolean('Section1', 'a_bool'):
print(config.get('Section1', 'foo'))
يجب استخدام الكائن ConfigParser
لإجراء عملية الاستيفاء:
import configparser
cfg = configparser.ConfigParser()
cfg.read('example.cfg')
# أسند القيمة True إلى المعامل *raw* في التابع get() إن كنت ترغب
# في تعطيل عملية الاستيفاء في إحدى عمليات get.
print(cfg.get('Section1', 'foo', raw=False)) # -> "Python is fun!"
print(cfg.get('Section1', 'foo', raw=True)) # -> "%(bar)s is %(baz)s!"
# المعامل الاختياري *vars* قاموس يتضمّن عناصر تأخذ
# الأسبقية على عملية الاستيفاء.
print(cfg.get('Section1', 'foo', vars={'bar': 'Documentation',
'baz': 'evil'}))
# يمكن استخدام المعامل الاختياري *fallback* لتوفير قيمة تراجعية
print(cfg.get('Section1', 'foo'))
# -> "Python is fun!"
print(cfg.get('Section1', 'foo', fallback='Monty is not.'))
# -> "Python is fun!"
print(cfg.get('Section1', 'monster', fallback='No such things as monsters.'))
# -> "No such things as monsters."
# لا يمكن استخدام التعبير
# print(cfg.get('Section1', 'monster'))
# وذلك لأنّه سيتسبب في إطلاق الاستثناء NoOptionError، ولكن يمكن استخدام:
print(cfg.get('Section1', 'monster', fallback=None))
# -> None
القيم الافتراضية متوفّرة في كلا نوعي الكائن ConfigParser
، وتستخدم هذه القيم في عملية الاستيفاء إن كان الخيار المستخدم غير معرّف في مكان آخر.
import configparser
# نسخة جديدة من الصنف مع تمرير القيم الافتراضية لكل خيار
config = configparser.ConfigParser({'bar': 'Life', 'baz': 'hard'})
config.read('example.cfg')
print(config.get('Section1', 'foo')) # -> "Python is fun!"
config.remove_option('Section1', 'bar')
config.remove_option('Section1', 'baz')
print(config.get('Section1', 'foo')) # -> "Life is hard!"
كائنات ConfigParser
تعدّ هذه الكائنات المفسّر الرئيسي لملفات الإعدادات.
كائنات RawConfigParser
هذه الكائنات هي النسخة القديمة من كائنات ConfigParser
.
استثناءات الوحدة configparser
الاستثناء configparser.Error
الصنف الأساسي الذي تتفرّع منه بقية الاستثناءات في وحدة configparser.
الاستثناء configparser.NoSectionError
يُطلق هذا الاستثناء عند عدم عثور المحلّل على قسم معيّن في ملف الإعدادات.
الاستثناء configparser.DuplicateSectionError
يُطلق هذا الاستثناء إن استدعي التابع add_section()
مع تمرير اسم لقسم موجودًا أصلًا في ملف الإعدادات، أو عند استخدام المحلّل في وضع التدقيق حين يعثر على قسمين يحملان الاسم ذاته في ملف أو سلسلة نصية أو قاموس واحد.
ملاحظة: أضيفت الخصائص والمعاملات الاختيارية source
و lineno
إلى التابع __init__()
في الإصدار 3.2 من بايثون.
الاستثناء configparser.DuplicateOptionError
يطلق هذا الاستثناء بواسطة المحللّات التي تعمل في وضع التدقيق إن تكرر ظهور أحد الخيارات أثناء قراءة البيانات من ملف أو سلسلة نصية أو قاموس واحد. ويمكن لهذا الاستثناء أن يلتقط الأخطاء الإملائية في الأسماء إضافة إلى الأخطاء المتعلقة بحالة الأحرف، فعلى سبيل المثال يمكن لقاموس أن يمتلك مفتاحين يمثّلان نفس مفتاح الإعدادات الذي لا يكون حساسًا لحالة الأحرف.
الاستثناء configparser.NoOptionError
يُطلق هذا الاستثناء عند عدم عثور المحلل على خيار معيّن في القسم المحدد.
الاستثناء configparser.InterpolationError
الصنف الأساسي الذي تتفرّع منه الاستثناءات التي تُطلق عند حدوث مشاكل أثناء إجراء عملية استيفاء السلاسل النصية.
الاستثناء configparser.InterpolationDepthError
يُطلق هذا الاستثناء عند عدم القدرة على إنهاء عملية استيفاء السلاسل النصية بسبب تجاوز عدد الدورات الحد الأقصى المعيّن في MAX_INTERPOLATION_DEPTH
. يتفرّع هذا الصنف من الصنف InterpolationError
.
الاستثناء configparser.InterpolationMissingOptionError
يُطلق هذا الاستثناء عند غياب الخيار الذي تشير إليه قيمة معيّنة. يتفرّع هذا الصنف من الصنف InterpolationError
.
الاستثناء configparser.InterpolationSyntaxError
يُطلق هذا الاستثناء عندما يكون النص المصدري الذي تجري فيه عملية الاستبدال غير متوافق مع الصيغة المطلوبة. يتفرّع هذا الصنف من الصنف InterpolationError
.
الاستثناء configparser.MissingSectionHeaderError
يُطلق هذا الاستثناء عند محاولة المحلل تحليل ملف لا يمتلك ترويسات العناوين.
الاستثناء configparser.ParsingError
يُطلق هذا الاستثناء عند حدوث أخطاء أثناء محاولة تحليل ملفّ معين.
ملاحظة: تغير اسم الخاصية ومعامل التابع __init__()
من filname
إلى tosource
في الإصدار 3.2 من بايثون.