تخيل الموقف: لقد كتبت بعض رمز Python الرائع الذي ينتج رسمًا بيانيًا جميلًا كإخراج. يمكنك حفظ هذا الرسم البياني ، بشكل طبيعي بما فيه الكفاية ، مثل graph.png . يمكنك تشغيل الكود عدة مرات ، في كل مرة تقوم بإجراء تعديلات طفيفة. عدت إليها في الأسبوع القادم/الشهر/السنة. هل تعرف كيف قمت بإنشاء هذا الرسم البياني؟ ما هي بيانات الإدخال؟ ما هو إصدار الكود الخاص بك؟ إذا كنت مثلي ، فستكون الإجابة في كثير من الأحيان ، محبطًا ، "لا". بالطبع ، أنت تضيع الكثير من الوقت في محاولة للتعرف على كيفية إنشائها ، أو حتى الاستسلام ولا تستخدمها أبدًا في ورقة اليومية هذه التي سيفوز بك جائزة نوبل ...
سيقدم هذا الحديث المربى (من الوصفة والبيثون ) ، وهي وحدة بيثون ستوفر لك من هذا الموقف! (على الرغم من أنه لا يمكن أن يضمن أن الورق الناتج الخاص بك سيفوز بجائزة نوبل!) مع إضافة سطر واحد من التعليمات البرمجية إلى أعلى ملفات Python الخاصة بك ، سيقوم الموفري بتسجيل كل عملية رمزك إلى قاعدة بيانات ، وتتبع تتبعها تتيح لك ملفات الإدخال وملفات الإخراج وإصدار الكود الخاص بك ، ثم يتيح لك الاستعلام عن قاعدة البيانات لمعرفة كيفية إنشاء graph.png بالفعل.
أسهل طريقة للتثبيت هي ببساطة التشغيل
pip install recipy
بدلاً من ذلك ، يمكنك استنساخ هذا المستودع وتشغيله:
python setup.py install
إذا كنت ترغب في تثبيت التبعيات يدويًا (يجب تثبيتها تلقائيًا إذا كنت تتابع التعليمات أعلاه) ثم قم بتشغيلها:
pip install -r requirements.txt
يمكنك الترقية من إصدار سابق عن طريق التشغيل:
pip install -U recipy
لمعرفة ما الذي تغير منذ الإصدار الأخير ، راجع changelog
ملاحظة: تتطلب إصدارات MongoDB السابقة (غير المنشورة) من MongoDB تثبيتها وإعدادها يدويًا. لم يعد هذا مطلوبًا ، حيث يتم استخدام قاعدة بيانات Python النقية (TinyDB) بدلاً من ذلك. أيضًا ، تم دمج واجهة المستخدم الرسومية الآن بشكل كامل في الموارد ولا تتطلب التثبيت بشكل منفصل.
ما عليك سوى إضافة السطر التالي إلى الجزء العلوي من نص Python الخاص بك:
import recipyلاحظ أن هذا يجب أن يكون السطر العلوي من البرنامج النصي الخاص بك ، قبل استيراد أي شيء آخر.
ثم قم فقط بتشغيل البرنامج النصي الخاص بك كالمعتاد ، وسيتم تسجيل جميع البيانات إلى قاعدة بيانات TinyDB (لا تقلق ، يتم إنشاء قاعدة البيانات تلقائيًا إذا لزم الأمر). يمكنك بعد ذلك استخدام البرنامج النصي recipy للاستعلام بسرعة عن قاعدة البيانات لمعرفة ما هو تشغيل رمزك الذي ينتج عنه ملف الإخراج. لذلك ، على سبيل المثال ، إذا قمت بتشغيل بعض التعليمات البرمجية مثل:
import recipy
import numpy
arr = numpy . arange ( 10 )
arr = arr + 500
numpy . save ( 'test.npy' , arr ) (لاحظ إضافة import recipy في بداية البرنامج النصي - ولكن لا توجد تغييرات أخرى من البرنامج النصي القياسي)
بدلاً من ذلك ، قم بتشغيل برنامج نصي غير معدّل مع python -m recipy SCRIPT [ARGS ...] لتمكين تسجيل المصل. يستدعي هذا نقطة إدخال وحدة المصل ، والتي تهتم بالاستيراد الموفرة لك ، قبل تشغيل البرنامج النصي الخاص بك.
سوف ينتج إخراجا يسمى test.npy . لمعرفة تفاصيل التشغيل الذي أنشأ هذا الملف الذي يمكنك البحث باستخدامه باستخدام
recipy search test.npy
وسوف يعرض معلومات مثل ما يلي:
Created by robin on 2015-05-25 19:00:15.631000
Ran /Users/robin/code/recipy/example_script.py using /usr/local/opt/python/bin/python2.7
Git: commit 91a245e5ea82f33ae58380629b6586883cca3ac4, in repo /Users/robin/code/recipy, with origin [email protected]:recipy/recipy.git
Environment: Darwin-14.3.0-x86_64-i386-64bit, python 2.7.9 (default, Feb 10 2015, 03:28:08)
Inputs:
Outputs:
/Users/robin/code/recipy/test.npy
طريقة بديلة لعرض ذلك هي استخدام واجهة المستخدم الرسومية. فقط قم بتشغيل recipy gui وسيتم فتح نافذة المتصفح مع واجهة يمكنك استخدامها للبحث في جميع "عمليات التشغيل" الخاصة بك:
إذا كنت ترغب في تسجيل الدخول والمخرجات من الملفات التي تقرأها أو مكتوبة مع Open Open ، فأنت بحاجة إلى القيام بمزيد من العمل. إما استخدام recipy.open (يتطلب فقط import recipy في الجزء العلوي من البرنامج النصي الخاص بك) ، أو أضف from recipy import open واستخدام open فقط. هذا الحل مطلوب ، لأن العديد من المكتبات تستخدم مفتوحة في داخلي ، وتريد فقط تسجيل الملفات التي فتحتها بشكل صريح.
إذا كنت تستخدم Python 2 ، فيمكنك تمرير معلمة encoding إلى recipy.open . في هذه الحالة ، يتم استخدام codecs لفتح الملف بالتشفير المناسب.
بمجرد حصولك على بعض التشغيل في قاعدة البيانات الخاصة بك ، يمكنك "التعليق" على هذه التشغيل مع أي ملاحظات تريد الاحتفاظ بها. يمكن أن يكون هذا مفيدًا بشكل خاص للتسجيل الذي يعمل بشكل جيد ، أو مشاكل معينة واجهتها. يمكن القيام بذلك من صفحة "التفاصيل" في واجهة المستخدم الرسومية ، أو عن طريق التشغيل
recipy annotate
الذي سيفتح محررًا للسماح لك بكتابة ملاحظات سيتم إرفاقها بالتشغيل. سيتم بعد ذلك عرضها عبر سطر الأوامر و GUI عند البحث عن عمليات التشغيل.
هناك ميزات أخرى في واجهة سطر الأوامر أيضًا: recipy --help لرؤية الخيارات الأخرى. يمكنك عرض الاختلافات ، ومشاهدة جميع عمليات التشغيل التي أنشأت ملفًا باسم معين ، والبحث بناءً على معرفات ، وإظهار أحدث الإدخال والمزيد:
recipy - a frictionless provenance tool for Python
Usage:
recipy search [options] <outputfile>
recipy latest [options]
recipy gui [options]
recipy annotate [<idvalue>]
recipy (-h | --help)
recipy --version
Options:
-h --help Show this screen
--version Show version
-a --all Show all results (otherwise just latest result given)
-f --fuzzy Use fuzzy searching on filename
-r --regex Use regex searching on filename
-i --id Search based on (a fragment of) the run ID
-v --verbose Be verbose
-d --diff Show diff
-j --json Show output as JSON
--no-browser Do not open browser window
--debug Turn on debugging mode
تخزن الموارد جميع تكوينه وقاعدة البيانات نفسها في ~/.recipy . يوجد ملف التكوين الرئيسي لـ Detry داخل هذا المجلد ، يسمى recipyrc . يعد تنسيق ملف التكوين بسيطًا للغاية ، ويستند إلى ملفات Windows INI - ويكون وجود ملف تكوين اختياريًا تمامًا: ستعمل الافتراضيات بشكل جيد بدون ملف تكوين.
تكوين مثال هو:
[ignored metadata]
diff
[general]
debug
هذا ببساطة يوجه الموارد بعدم حفظ معلومات git diff عندما يسجل البيانات الوصفية حول التشغيل ، وأيضًا لطباعة رسائل التصحيح (والتي يمكن أن تكون مفيدة حقًا إذا كنت تحاول معرفة سبب عدم تصحيح الوظائف). في الوقت الحالي ، الخيارات الممكنة الوحيدة هي:
[general]debug - طباعة رسائل التصحيحeditor = vi - قم بتكوين محرر النص الافتراضي الذي سيتم استخدامه عند الحاجة إلى تكتبك في رسالة. استخدم المفكرة إذا على Windows ، على سبيل المثالquiet - لا تطبع أي رسائلport - حدد المنفذ لاستخدامه في واجهة المستخدم الرسومية[data]file_diff_outputs - تخزين Diff بين الإخراج القديم وملف الإخراج الجديد ، إذا كان ملف الإخراج موجودًا قبل تنفيذ البرنامج النصي[database]path = /path/to/file.json - اضبط المسار على ملف قاعدة البيانات[ignored metadata]diff - لا تخزن إخراج git diff في البيانات الوصفية لتشغيل الموفرةgit - لا تخزن أي شيء يتعلق بـ git (الأصل ، الالتزام ، repo etc) في البيانات الوصفية لتشغيل المربىinput_hashes - لا تحسب وتخزين تجزئة SHA -1 من ملفات الإدخالoutput_hashes - لا تحسب وتخزين تجزئة SHA -1 من ملفات الإخراج[ignored inputs]all أي وحدة هنا (على سبيل numpy[ignored outputs]all (على سبيل numpy بشكل افتراضي ، يتم تخزين جميع البيانات الوصفية (أي لا يتم تجاهل البيانات الوصفية) ولا يتم عرض رسائل التصحيح. يتمتع ملف .recipyrc في الدليل الحالي بالأسبقية على ملف ~/.recipy/recipyrc ، مما يسمح بالتعامل مع تكوينات لكل مشروع بسهولة.
ملاحظة: لا يتم تزويد ملف التكوين الافتراضي مع المربى ، لذلك إذا كنت ترغب في تكوين أي شيء ستحتاجه لإنشاء ملف تنسيقه بنفسك.
عند استيراد المصل ، يضيف عددًا من الفصول إلى sys.meta_path . ثم يتم استخدامها بواسطة Python كجزء من الإجراء المستورد للوحدات النمطية. الفصول الدراسية التي نضيفها هي فئات مستمدة من PatchImporter ، وغالبًا ما تستخدم الواجهة الأسهل التي يوفرها PatchSimple ، والتي تتيح لنا لف وظائف القيام بالإدخال/الإخراج في وظيفة تستدعي المصل أولاً لتسجيل المعلومات.
بشكل عام ، يتم إخفاء معظم التعقيد في PatchImporter و PatchSimple (بالإضافة إلى utils.py ) ، وبالتالي فإن الكود الفعلي للف وحدة ، مثل numpy بسيط إلى حد ما:
# Inherit from PatchSimple
class PatchNumpy ( PatchSimple ):
# Specify the full name of the module
modulename = 'numpy'
# List functions that are involved in input/output
# these can be anything that can go after "modulename."
# so they could be something like "pyplot.savefig" for example
input_functions = [ 'genfromtxt' , 'loadtxt' , 'load' , 'fromfile' ]
output_functions = [ 'save' , 'savez' , 'savez_compressed' , 'savetxt' ]
# Define the functions that will be used to wrap the input/output
# functions.
# In this case we are calling the log_input function to log it to the DB
# and we are giving it the 0th argument from the function (because all of
# the functions above take the filename as the 0th argument), and telling
# it that it came from numpy.
input_wrapper = create_wrapper ( log_input , 0 , 'numpy' )
output_wrapper = create_wrapper ( log_output , 0 , 'numpy' )يجب تنفيذ فئة كهذه لكل وحدة تحتاج إلى تسجيل الدخول/الإخراج. في الوقت الحالي ، يتم تصحيح وظائف الإدخال والإخراج التالية:
يسرد هذا الجدول أن الوحدات النمطية لها تصحيحات ، ووظائف الإدخال والمخرجات التي يتم تصحيحها.
| الوحدة النمطية | وظائف الإدخال | وظائف الإخراج |
|---|---|---|
pandas | read_csv ، read_table ، read_excel ، read_hdf ، read_pickle ، read_stata ، read_msgpack | DataFrame.to_csv ، DataFrame.to_excel ، DataFrame.to_hdf ، DataFrame.to_msgpack ، DataFrame.to_stata ، DataFrame.to_pickle ، Panel.to_excel ، Panel.to_hdf ، Panel.to_msgpack ، Panel.to_pickle Series.to_csv Series.to_hdf ، Series.to_msgpack ، Series.to_pickle |
matplotlib.pyplot | savefig | |
numpy | genfromtxt ، loadtxt ، fromfile | save ، savez ، savez_compressed ، savetxt |
lxml.etree | parse ، iterparse | |
bs4 | BeautifulSoup | |
gdal | Open | Driver.Create ، Driver.CreateCopy |
sklearn | datasets.load_svmlight_file | datasets.dump_svmlight_file |
nibabel | nifti1.Nifti1Image.from_filename ، nifti2.Nifti2Image.from_filename ، freesurfer.mghformat.MGHImage.from_filename ، spm99analyze.Spm99AnalyzeImage.from_filename ، minc1.Minc1Image.from_filename ، minc2.Minc2Image.from_filename ، analyze.AnalyzeImage.from_filename ، parrec.PARRECImage.from_filename ، spm2analyze.Spm2AnalyzeImage.from_filename | nifti1.Nifti1Image.to_filename ، nifti2.Nifti2Image.to_filename ، freesurfer.mghformat.MGHImage.to_filename ، spm99analyze.Spm99AnalyzeImage.to_filename minc2.Minc2Image.to_filename minc1.Minc1Image.to_filename analyze.AnalyzeImage.to_filename ، parrec.PARRECImage.to_filename ، spm2analyze.Spm2AnalyzeImage.to_filename |
ومع ذلك ، يوضح مثال الكود أعلاه مدى سهولة كتابة فصل لفصل وحدة جديدة - لذا لا تتردد في تقديم طلب سحب لجعل الموارد تعمل مع الوحدات العلمية المفضلة لديك!
إطار اختبار revy في integration_test . تم تصميم إطار الاختبار ليتم تشغيله تحت كل من Python 2.7+ و Python 3+. لمزيد من المعلومات ، راجع إطار اختبار الموفرين.
يتم تشغيل إطار الاختبار على المنصات التالية: