نصائح وحيل للمطورين#
نصائح للحفاظ على الإنتاجية والعقل#
في هذا القسم، نجمع بعض النصائح والأدوات المفيدة التي قد تزيد من جودة حياتك عند مراجعة طلبات السحب، وتشغيل اختبارات الوحدة، وما إلى ذلك. تتكون بعض هذه الحيل من برامج نصية للمستخدمين تتطلب امتدادًا للمتصفح مثل TamperMonkey أو GreaseMonkey؛ لإعداد برامج نصية للمستخدمين، يجب أن يكون لديك أحد هذه الامتدادات مثبتًا ومُفعلاً وقيد التشغيل. نحن نقدم برامج نصية للمستخدمين كـ GitHub gists؛ لتثبيتها، انقر فوق الزر "خام" في صفحة gist.
طي وفرد الاختلافات القديمة في طلبات السحب#
يخفي GitHub المناقشات على طلبات السحب عندما يتم تغيير أسطر التعليمات البرمجية المقابلة في هذه الأثناء. هذا البرنامج النصي للمستخدم يوفر اختصارًا (Control-Alt-P في وقت الكتابة ولكن انظر إلى الشفرة للتأكد) لفرد جميع هذه المناقشات المخفية مرة واحدة، حتى تتمكن من اللحاق بالركب.
التحقق من طلبات السحب كفروع تتبع عن بُعد#
في الشوكة المحلية الخاصة بك، أضف إلى .git/config
الخاص بك، ضمن عنوان [remote
"upstream"]
، السطر:
fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*
يمكنك بعد ذلك استخدام git checkout pr/PR_NUMBER
للانتقال إلى شفرة
طلب السحب بالرقم المحدد. (اقرأ المزيد في هذا gist.)
عرض تغطية الشفرة في طلبات السحب#
لتراكب تقارير تغطية الشفرة التي تم إنشاؤها بواسطة تكامل CodeCov المستمر، ضع في اعتبارك امتداد المتصفح هذا. سيتم عرض تغطية كل سطر كخلفية ملونة خلف رقم السطر.
أسماء مستعارة وأعلام pytest مفيدة#
تستغرق مجموعة الاختبارات الكاملة وقتًا طويلاً للتشغيل. من أجل التكرارات الأسرع، من الممكن تحديد مجموعة فرعية من الاختبارات باستخدام محددات pytest. على وجه الخصوص، يمكن للمرء تشغيل اختبار واحد بناءً على معرف العقدة الخاص به:
pytest -v sklearn/linear_model/tests/test_logistic.py::test_sparsify
أو استخدم معلمة pytest -k لتحديد الاختبارات بناءً على اسمها. فمثلا،:
pytest sklearn/tests/test_common.py -v -k LogisticRegression
سيُشغِّل جميع الاختبارات الشائعة لمقدر LogisticRegression
.
عندما يفشل اختبار وحدة، يمكن للحيل التالية أن تجعل تصحيح الأخطاء أسهل:
تُرشد وسيطة سطر الأوامر
pytest -l
pytest إلى طباعة المتغيرات المحلية عند حدوث فشل.تنزل الوسيطة
pytest --pdb
في مُصحِّح أخطاء Python عند الفشل. لـ تنزيل مُصحِّح أخطاء IPython الغنيipdb
بدلاً من ذلك، يمكنك إعداد اسم مستعار shell لـ:pytest --pdbcls=IPython.terminal.debugger:TerminalPdb --capture no
خيارات pytest
الأخرى التي قد تصبح مفيدة تشمل:
-x
الذي يخرج عند أول اختبار فاشل،--lf
لإعادة تشغيل الاختبارات التي فشلت في التشغيل السابق،--ff
لإعادة تشغيل جميع الاختبارات السابقة، وتشغيل الاختبارات التي فشلت أولاً،-s
بحيث لا يلتقط pytest ناتج عباراتprint()
،--tb=short
أو--tb=line
للتحكم في طول السجلات،--runxfail
أيضًا تشغيل الاختبارات التي تم تمييزها على أنها فشل معروف (XFAIL) والإبلاغ عن الأخطاء.
نظرًا لأن اختبارات التكامل المستمر الخاصة بنا ستفشل إذا
لم يتم اكتشاف FutureWarning
بشكل صحيح،
فمن المستحسن أيضًا تشغيل pytest
مع
علم -Werror::FutureWarning
.
ردود قياسية للمراجعة#
قد يكون من المفيد تخزين بعض هذه في الردود المحفوظة لـ GitHub للمراجعة:
المشكلة: أسئلة الاستخدام
أنت تسأل سؤال استخدام. متتبع المشكلات مخصص للأخطاء والميزات الجديدة. بالنسبة لأسئلة الاستخدام، يُوصى بتجربة [Stack Overflow](https://stackoverflow.com/questions/tagged/scikit-learn) أو [قائمة البريد](https://mail.python.org/mailman/listinfo/scikit-learn).
لسوء الحظ، نحتاج إلى إغلاق هذه المشكلة حيث أن متتبع المشكلات هذا هو أداة اتصال تُستخدم لتطوير scikit-learn. النشاط الإضافي الناتج عن أسئلة الاستخدام يزدحم كثيرًا ويعيق هذا التطوير. يمكن أن تستمر المحادثة هنا، ولكن لا يوجد ضمان بأنها ستتلقى اهتمامًا من المطورين الأساسيين.
المشكلة: نرحب بتحديث المستندات
لا تتردد في تقديم طلب سحب لتحديث الوثائق إذا كنت تشعر أنه يمكن تحسينها.
المشكلة: مثال قائم بذاته للخطأ
يرجى تقديم [مثال شفرة قائم بذاته](https://scikit-learn.org/dev/developers/minimal_reproducer.html)، بما في ذلك عمليات الاستيراد والبيانات (إن أمكن)، حتى يتمكن المساهمون الآخرون من تشغيله وإعادة إنتاج مشكلتك. من الناحية المثالية، يجب أن يكون مثال الشفرة الخاص بك بسيطًا.
المشكلة: إصدارات البرنامج
لمساعدتك في تشخيص مشكلتك، يرجى لصق ناتج:
```py
import sklearn; sklearn.show_versions()
```
شكرًا.
المشكلة: كتل التعليمات البرمجية
يمكن تحسين قابلية القراءة بشكل كبير إذا قمت [بتنسيق](https://help.github.com/articles/creating-and-highlighting-code-blocks/) مقتطفات التعليمات البرمجية الخاصة بك ورسائل الخطأ الكاملة بشكل مناسب. فمثلا:
```python
print(something)
```
يولد:
```python
print(something)
```
و:
```pytb
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'hello'
```
يولد:
```pytb
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'hello'
```
يمكنك تعديل أوصاف المشكلات وتعليقاتك في أي وقت لتحسين قابلية القراءة. هذا يساعد المسؤولين كثيرًا. شكرًا!
المشكلة/التعليق: ربط بالشفرة
نصيحة ودية: من أجل الوضوح، يمكنك ربط الشفرة مثل [هذا](https://help.github.com/articles/creating-a-permanent-link-to-a-code-snippet/).
المشكلة/التعليق: ربط بالتعليقات
يرجى استخدام روابط للتعليقات، مما يسهل رؤية ما تشير إليه، بدلاً من مجرد ربط بالمشكلة. انظر [هذا](https://stackoverflow.com/questions/25163598/how-do-i-reference-a-specific-issue-comment-on-github) لمزيد من التفاصيل.
PR-NEW: وصف وعنوان أفضل
شكرًا على طلب السحب! يرجى جعل عنوان طلب السحب أكثر وصفية. سيصبح العنوان رسالة الإيداع عند دمج هذا. يجب أن تُذكر المشكلة (أو طلب السحب) التي يتم إصلاحها/حلها في الوصف باستخدام بناء الجملة الموضح [هنا](https://scikit-learn.org/dev/developers/contributing.html#contributing-pull-requests).
PR-NEW: إصلاح #
يرجى استخدام "Fix #issueNumber" في وصف طلب السحب الخاص بك (ويمكنك القيام بذلك أكثر من مرة). بهذه الطريقة، يتم إغلاق المشكلة المرتبطة تلقائيًا عند دمج طلب السحب. لمزيد من التفاصيل، انظر إلى [هذا](https://github.com/blog/1506-closing-issues-via-pull-requests).
PR-NEW أو المشكلة: تكلفة الصيانة
كل ميزة نقوم بتضمينها لها [تكلفة صيانة](https://scikit-learn.org/dev/faq.html#why-are-you-so-selective-on-what-algorithms-you-include-in-scikit-learn). المسؤولين لدينا هم في الغالب متطوعون. لكي يتم تضمين ميزة جديدة، نحتاج إلى دليل على أنها مفيدة في كثير من الأحيان، ومن الناحية المثالية، [راسخة](https://scikit-learn.org/dev/faq.html#what-are-the-inclusion-criteria-for-new-algorithms) في الأدبيات أو في الممارسة. أيضًا، نتوقع من مؤلفي طلبات السحب المشاركة في صيانة الشفرة التي يقدمونها، على الأقل في البداية. هذا لا يمنعك من تنفيذها بنفسك ونشرها في مستودع منفصل، أو حتى [scikit-learn-contrib](https://scikit-learn-contrib.github.io).
PR-WIP: ما المطلوب قبل الدمج؟
يرجى توضيح (ربما كقائمة مهام في وصف طلب السحب) العمل الذي تعتقد أنه لا يزال بحاجة إلى القيام به قبل أن تتم مراجعته للدمج. عندما يكون جاهزًا، يرجى إضافة بادئة `[MRG]` إلى عنوان طلب السحب.
PR-WIP: اختبار الانحدار مطلوب
يرجى إضافة [اختبار عدم الانحدار](https://en.wikipedia.org/wiki/Non-regression_testing) الذي سيفشل في الرئيسي ولكنه سينجح في طلب السحب هذا.
PR-WIP: PEP8
لديك بعض انتهاكات [PEP8](https://www.python.org/dev/peps/pep-0008/)، والتي يمكنك رؤية تفاصيلها في وظيفة Circle CI `lint`. قد يكون من المفيد تكوين محرر التعليمات البرمجية الخاص بك للتحقق من هذه الأخطاء أثناء التنقل، حتى تتمكن من اكتشافها قبل الالتزام.
PR-MRG: الصبر
قبل الدمج، نطلب عمومًا من مطورين أساسيين الموافقة على أن طلب السحب الخاص بك مرغوب فيه وجاهز. [يرجى التحلي بالصبر](https://scikit-learn.org/dev/faq.html#why-is-my-pull-request-not-getting-any-attention)، حيث أننا نعتمد في الغالب على وقت التطوع من المطورين الأساسيين المشغولين. (نرحب بك أيضًا لمساعدتنا في [مراجعة طلبات السحب الأخرى](https://scikit-learn.org/dev/developers/contributing.html#code-review-guidelines)).
PR-MRG: أضف إلى الجديد
يرجى إضافة إدخال إلى سجل التغيير في `doc/whats_new/v*.rst`. مثل الإدخالات الأخرى هناك، يرجى الرجوع إلى طلب السحب هذا باستخدام `:pr:` وتسجيل نفسك (والمساهمين الآخرين إن أمكن) باستخدام `:user:`.
PR: لا تقم بتغيير غير ذي صلة
يرجى عدم تغيير الأسطر غير ذات الصلة. يجعل مساهمتك أكثر صعوبة في المراجعة وقد يُسبب تعارضات دمج مع طلبات سحب أخرى.
تصحيح أخطاء مشكلات CI#
قد تنشأ مشكلات CI لأسباب متنوعة، لذا فهذا ليس بأي حال من الأحوال دليلاً شاملاً، ولكنه بالأحرى قائمة بالنصائح والحيل المفيدة.
استخدام ملف قفل للحصول على بيئة قريبة من CI#
يمكن استخدام conda-lock
لإنشاء بيئة conda بنفس
حزم conda و pip الموجودة على CI. على سبيل المثال، سيُنشئ الأمر التالي
بيئة conda تسمى scikit-learn-doc
تشبه CI:
conda-lock install -n scikit-learn-doc build_tools/circle/doc_linux-64_conda.lock
ملاحظة
يعمل هذا فقط إذا كان لديك نفس نظام التشغيل مثل تصميم CI (تحقق من platform:
في
ملف القفل). على سبيل المثال، لن يعمل الأمر السابق إلا إذا كنت
على جهاز Linux. أيضًا، قد لا يسمح لك هذا بإعادة إنتاج بعض
المشكلات الأكثر ارتباطًا بخصائص بيئة CI، على
سبيل المثال، بنية وحدة المعالجة المركزية التي أبلغ عنها OpenBLAS في sklearn.show_versions()
.
إذا لم يكن لديك نفس نظام التشغيل مثل تصميم CI، فلا يزال بإمكانك إنشاء بيئة conda من ملف yaml البيئة الصحيح، على الرغم من أنها لن تكون قريبة مثل بيئة CI مثل استخدام ملف القفل المرتبط. على سبيل المثال، بالنسبة لـ تصميم المستندات:
conda env create -n scikit-learn-doc -f build_tools/circle/doc_environment.yml -y
قد لا يمنحك هذا نفس إصدارات الحزم تمامًا كما في CI لعدة أسباب، على سبيل المثال:
قد يكون لدى بعض الحزم إصدارات جديدة بين وقت آخر تحديث لملفات القفل في فرع
main
ووقت تشغيل أمرconda create
. يمكنك دائمًا محاولة إلقاء نظرة على الإصدار في ملف القفل و تحديد الإصدارات يدويًا لبعض الحزم المحددة التي تعتقد أنها ستساعد في إعادة إنتاج المشكلة.قد يتم تثبيت حزم مختلفة افتراضيًا اعتمادًا على نظام التشغيل. على سبيل المثال، مكتبة BLAS الافتراضية عند تثبيت numpy هي OpenBLAS على Linux و MKL على Windows.
أيضًا، قد تكون المشكلة خاصة بنظام التشغيل، لذا فإن الطريقة الوحيدة لإعادة الإنتاج ستكون أن يكون لديك نفس نظام التشغيل مثل تصميم CI.
تصحيح أخطاء الذاكرة في Cython باستخدام valgrind#
على الرغم من أن إدارة الذاكرة المضمنة في python/numpy قوية نسبيًا، إلا أنها يمكن أن تؤدي إلى عقوبات على الأداء بالنسبة لبعض الإجراءات. لهذا السبب، تمت كتابة الكثير من الشفرة عالية الأداء في scikit-learn في cython. ومع ذلك، فإن هذا المكسب في الأداء يأتي مع مقايضة: من السهل جدًا ظهور أخطاء الذاكرة في كود cython، خاصة في المواقف التي تعتمد فيها هذه الشفرة بشكل كبير على حساب المؤشر.
يمكن أن تظهر أخطاء الذاكرة بعدة طرق. أسهل ما يمكن تصحيحه غالبًا ما يكون أخطاء التجزئة وأخطاء glibc ذات الصلة. يمكن أن تؤدي المتغيرات غير المهيأة إلى سلوك غير متوقع يصعب تتبعه. أداة مفيدة للغاية عند تصحيح هذا النوع من الأخطاء هي valgrind.
Valgrind هي أداة سطر أوامر يمكنها تتبع أخطاء الذاكرة في مجموعة متنوعة من التعليمات البرمجية. اتبع هذه الخطوات:
قم بتثبيت valgrind على نظامك.
قم بتنزيل ملف منع valgrind python: valgrind-python.supp.
اتبع التعليمات الموجودة في ملف README.valgrind لتخصيص عمليات منع python الخاصة بك. إذا لم تفعل ذلك، فسيكون لديك ناتج زائف قادم يتعلق بمترجم python بدلاً من التعليمات البرمجية الخاصة بك.
قم بتشغيل valgrind على النحو التالي:
valgrind -v --suppressions=valgrind-python.supp python my_test_script.py
ستكون النتيجة قائمة بجميع الأخطاء المتعلقة بالذاكرة، والتي تشير إلى أسطر في كود C الذي تم إنشاؤه بواسطة cython من ملف .pyx الخاص بك. إذا قمت بفحص الأسطر المشار إليها في ملف .c، فسترى تعليقات تشير إلى الموقع المقابل في ملف المصدر .pyx الخاص بك. نأمل أن يمنحك الناتج أدلة على مصدر خطأ الذاكرة الخاص بك.
لمزيد من المعلومات حول valgrind ومجموعة الخيارات المتاحة له، انظر البرامج التعليمية والوثائق على موقع valgrind الإلكتروني.
البناء والاختبار لمنصة ARM64 على جهاز x86_64#
تُعد الأجهزة المستندة إلى ARM هدفًا شائعًا للنشر على الأجهزة المحمولة أو الطرفية أو عمليات النشر الأخرى منخفضة الطاقة (بما في ذلك في السحابة، على سبيل المثال على Scaleway أو AWS Graviton).
فيما يلي تعليمات لإعداد بيئة تطوير محلية لإعادة إنتاج الأخطاء الخاصة بـ ARM أو فشل الاختبارات على كمبيوتر محمول أو محطة عمل x86_64 المضيفة. يعتمد هذا على محاكاة وضع مستخدم QEMU باستخدام docker للراحة (انظر multiarch/qemu-user-static).
ملاحظة
تم توضيح التعليمات التالية لـ ARM64 ولكنها تنطبق أيضًا على ppc64le، بعد تغيير صورة Docker ومسارات Miniforge بشكل مناسب.
قم بإعداد مجلد على نظام ملفات المضيف وقم بتنزيل الأدوات اللازمة وشفرة المصدر:
mkdir arm64
pushd arm64
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh
git clone https://github.com/scikit-learn/scikit-learn.git
استخدم docker لتثبيت وضع مستخدم QEMU وتشغيل حاوية ARM64v8 مع الوصول
إلى المجلد المشترك الخاص بك ضمن نقطة التحميل /io
:
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker run -v`pwd`:/io --rm -it arm64v8/ubuntu /bin/bash
في الحاوية، قم بتثبيت miniforge3 لهندسة ARM64 (المعروفة أيضًا باسم aarch64):
bash Miniforge3-Linux-aarch64.sh
# اختر تثبيت miniforge3 ضمن: `/io/miniforge3`
كلما أعدت تشغيل حاوية جديدة، ستحتاج إلى إعادة تهيئة بيئة conda
المثبتة مسبقًا ضمن /io/miniforge3
:
/io/miniforge3/bin/conda init
source /root/.bashrc
حيث أن المجلد الرئيسي /root
هو جزء من حاوية docker المؤقتة. كل
ملف أو دليل مخزن تحت /io
يكون ثابتًا من ناحية أخرى.
يمكنك بعد ذلك بناء scikit-learn كالمعتاد (ستحتاج إلى تثبيت أدوات
المترجم والتبعيات باستخدام apt أو conda كالمعتاد). يستغرق بناء scikit-learn
وقتًا طويلاً بسبب طبقة المحاكاة، ولكن يلزم
إجراؤه مرة واحدة فقط إذا وضعت مجلد scikit-learn ضمن نقطة التحميل /io
.
ثم استخدم pytest لتشغيل اختبارات الوحدة التي تهتم بتصحيحها فقط.
الخلفية الخلفية لبناء Meson#
منذ scikit-learn 1.5.0، نستخدم meson-python كأداة بناء. Meson هي أداة جديدة لـ scikit-learn ونظام PyData البيئي. يتم استخدامه من قبل العديد من الحزم الأخرى التي كتبت أدلة جيدة حول ماهيته وكيف يعمل.
وثيقة إعداد pandas: لدى pandas إعداد مشابه لإعدادنا (بدون spin أو dev.py)
وثيقة scipy Meson تقدم مزيدًا من المعلومات الأساسية حول كيفية عمل Meson وراء الكواليس