想像一下情況:您已經編寫了一些很棒的Python代碼,該代碼可產生美麗的圖形作為輸出。您自然地將該圖保存為graph.png
。您每次進行次要修改,都會運行幾次代碼。您下週/月/年回到它。您知道如何創建該圖嗎?什麼輸入數據?哪個版本的代碼?如果您像我一樣,那麼答案通常會令人沮喪地“不”。當然,然後,您浪費了很多時間試圖弄清楚自己的創建方式,甚至放棄,也從未在那張期刊論文中使用它,以贏得諾貝爾獎……
這次演講將介紹食譜(來自食譜和Python ),這是一個python模塊,可以使您免於這種情況! (儘管不能保證您的紙張會贏得諾貝爾獎!)在您的Python文件的頂部增加一系列代碼,食譜將使您的代碼每次運行記錄到數據庫,並跟踪輸入文件,輸出文件和代碼的版本,然後讓您查詢此數據庫,以了解實際上如何創建graph.png
。
最簡單的安裝方法是簡單地運行
pip install recipy
另外,您可以克隆此存儲庫並運行:
python setup.py install
如果您想手動安裝依賴項(如果您按照上述說明,應自動安裝它們),請運行:
pip install -r requirements.txt
您可以通過運行以前的版本升級:
pip install -U recipy
要了解自上次發行以來發生了什麼變化,請參閱ChangElog
注意:以上(未發行的)配方版本需要安裝MongoDB並手動設置。這不再需要,因為使用純Python數據庫(TinyDB)。此外,GUI現在已完全集成到食譜中,不需要單獨安裝。
只需在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
查看此問題的另一種方法是使用GUI。只需運行recipy gui
和瀏覽器窗口即可使用一個接口打開,您可以使用該界面來搜索所有食譜“運行”:
如果要記錄使用內置打開或編寫文件的文件的輸入和輸出,則需要做更多的工作。要么使用recipy.open
(僅需要在腳本的頂部import recipy
),要么from recipy import open
,然後只使用open
。需要此解決方法,因為許多庫在內部使用內置打開,而您只想記錄您自己打開的文件。
如果您使用Python 2,則可以將encoding
參數傳遞給recipy.open
。在這種情況下, codecs
用於使用適當的編碼打開文件。
一旦您的數據庫中有一些運行,就可以“註釋”這些運行,並帶有任何要保留的註釋。這對於錄製運行良好的錄製或您遇到的特定問題可能特別有用。這可以從GUI中的“詳細信息”頁面或運行
recipy annotate
它將打開一個編輯器,以允許您編寫將附加到運行中的筆記。然後在搜索運行時通過命令行和GUI可查看這些。
命令行界面中也有其他功能: recipy --help
來查看其他選項。您可以查看diffs,查看創建具有給定名稱的文件的所有運行,基於ID搜索,顯示最新條目等:
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
中。配方的主要配置文件在此文件夾中,稱為recipyrc
。配置文件格式非常簡單,並且基於Windows INI文件 - 配置文件是完全可選的:默認值在沒有配置文件的情況下可以正常工作。
一個示例配置是:
[ignored metadata]
diff
[general]
debug
這只是指示食譜在記錄元數據有關運行的元數據時不要保存git diff
信息,還要打印調試消息(如果您試圖弄清楚為什麼未修補某些功能,這將非常有用)。目前,唯一可能的選項是:
[general]
debug
- 打印調試消息editor = vi
配置默認文本編輯器,當食譜需要您輸入消息時將使用。例如,如果在Windows上使用Notepadquiet
- 不要打印任何消息port
- 指定用於GUI的端口[data]
file_diff_outputs
如果執行腳本之前的輸出文件存在,則存儲舊輸出和新輸出文件之間的差異[database]
path = /path/to/file.json
to/file.json-將路徑設置為數據庫文件[ignored metadata]
diff
不要將git diff
的輸出存儲在元數據中以進行配方運行git
不要在元數據中存儲與git(原始,提交,回購等)有關的任何內容input_hashes
不要計算輸入文件的SHA -1哈希output_hashes
不要計算和存儲輸出文件的SHA -1哈希[ignored inputs]
numpy
),以指示食譜不記錄該模塊的輸入,或者all
忽略所有模塊的輸入[ignored outputs]
numpy
),以指示食譜不記錄此模塊的輸出,或者all
忽略所有模塊的輸出默認情況下,所有元數據都存儲了(即。沒有忽略元數據),並且未顯示調試消息。當前目錄中的一個.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_msgpack , DataFrame.to_stata ,panel.to_excel, DataFrame.to_pickle , Panel.to_excel , Panel.to_hdf , Panel.to_msgpack , Panel.to_pickle ,sermerser. tos.to.to.to.to.to.to.to.to, 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 , minc1.Minc1Image.to_filename , minc2.Minc2Image.to_filename , analyze.AnalyzeImage.to_filename , parrec.PARRECImage.to_filename , spm2analyze.Spm2AnalyzeImage.to_filename |
但是,上面的代碼示例顯示了編寫課程以包裝新模塊的容易 - 因此,請隨時提交拉動請求,以使食譜與您最喜歡的科學模塊合作!
食譜的測試框架在integration_test
中。測試框架已設計為在Python 2.7+和Python 3+下運行。有關更多信息,請參見配方測試框架。
測試框架在以下平台上運行: