Imagine la situación: ha escrito un maravilloso código de pitón que produce un gráfico hermoso como salida. Guardas ese gráfico, naturalmente, como graph.png
. Ejecuta el código un par de veces, cada vez que hace modificaciones menores. Vuelve a él la próxima semana/mes/año. ¿Sabes cómo creaste ese gráfico? ¿Qué datos de entrada? ¿Qué versión de tu código? Si eres como yo, la respuesta a menudo, frustrantemente, será "no". Por supuesto, luego pierde mucho tiempo tratando de averiguar cómo lo creó, o incluso rendirse y nunca usarlo en ese artículo de revista que le gane un Premio Nobel ...
¡Esta charla presentará Recipy (de Recipe y Python ), un módulo de Python que lo salvará de esta situación! (¡Aunque no puede garantizar que su documento resultante gane un premio Nobel!) Con la adición de una sola línea de código a la parte superior de sus archivos de Python, Recipy registrará cada ejecución de su código a una base de datos, realizando un seguimiento de Los archivos de entrada, los archivos de salida y la versión de su código, y luego le permiten consultar esta base de datos para averiguar cómo realmente creó graph.png
.
La forma más fácil de instalar es simplemente ejecutando
pip install recipy
Alternativamente, puede clonar este repositorio y ejecutar:
python setup.py install
Si desea instalar las dependencias manualmente (deben instalarse automáticamente si sigue las instrucciones anteriores), ejecute:
pip install -r requirements.txt
Puede actualizar desde una versión anterior ejecutando:
pip install -U recipy
Para averiguar qué ha cambiado desde el último lanzamiento, vea el ChangeLog
NOTA: Las versiones anteriores (inéditas) de receta requerían que MongoDB se instale y se configure manualmente. En su lugar, esto ya no se requiere, ya que se usa una base de datos de Python pura (TinyDB). Además, la GUI ahora está integrada completamente en Recipy y no requiere la instalación por separado.
Simplemente agregue la siguiente línea a la parte superior de su script de Python:
import recipy
Tenga en cuenta que esta debe ser la línea superior de su script, antes de importar cualquier otra cosa.
Luego, simplemente ejecute su script como de costumbre, y todos los datos se registrarán en la base de datos TinyDB (no se preocupe, la base de datos se crea automáticamente si es necesario). Luego puede usar el script recipy
para consultar rápidamente la base de datos para averiguar qué ejecución de su código produjo qué archivo de salida. Entonces, por ejemplo, si ejecuta algún código como este:
import recipy
import numpy
arr = numpy . arange ( 10 )
arr = arr + 500
numpy . save ( 'test.npy' , arr )
(Tenga en cuenta la adición de import recipy
al comienzo del script, pero no hay otros cambios de un script estándar)
Alternativamente, ejecute un script no modificado con python -m recipy SCRIPT [ARGS ...]
para habilitar el registro receptor. Esto invoca el punto de entrada del módulo de Recipy, que se encarga de la recípica de importación para usted, antes de ejecutar su script.
Producirá una salida llamada test.npy
. Para conocer los detalles de la ejecución que creó este archivo que puede buscar usando
recipy search test.npy
y mostrará información como la siguiente:
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
Una forma alternativa de ver esto es usar la GUI. Simplemente ejecute recipy gui
y una ventana de navegador se abrirá con una interfaz que puede usar para buscar todas sus 'ejecuciones' receptivas:
Si desea registrar entradas y salidas de archivos leídos o escritos con Open incorporado, debe hacer un poco más de trabajo. import recipy
recipy.open
from recipy import open
open
Se requiere esta solución, porque muchas bibliotecas usan Open Interviado internamente, y solo desea grabar los archivos que se abrió explícitamente.
Si usa Python 2, puede pasar un parámetro encoding
a recipy.open
. En este caso, codecs
se usan para abrir el archivo con la codificación adecuada.
Una vez que tenga algunas ejecuciones en su base de datos, puede 'anotar' estas ejecuciones con cualquier nota que desee conservar sobre ellas. Esto puede ser particularmente útil para la grabación que funcionó bien, o problemas particulares en los que se encontró. Esto se puede hacer a partir de la página 'Detalles' en la GUI, o ejecutando
recipy annotate
que abrirá un editor para permitirle escribir notas que se adjuntarán a la ejecución. Estos se pueden ver a través de la línea de comandos y la GUI al buscar ejecuciones.
También hay otras características en la interfaz de línea de comandos: recipy --help
para ver las otras opciones. Puede ver diffs, ver todas las ejecuciones que crearon un archivo con un nombre de hecho, buscar en base a ID, mostrar la última entrada y más:
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 almacena toda su configuración y la base de datos en sí en ~/.recipy
. El archivo de configuración principal de Recipy está dentro de esta carpeta, llamado recipyrc
. El formato de archivo de configuración es muy simple y se basa en archivos Windows INI, y tener un archivo de configuración es completamente opcional: los valores predeterminados funcionarán bien sin ningún archivo de configuración.
Una configuración de ejemplo es:
[ignored metadata]
diff
[general]
debug
Esto simplemente instruye a Recipy que no guarde la información de git diff
cuando registra metadatos sobre una ejecución, y también para imprimir mensajes de depuración (lo que puede ser realmente útil si está tratando de averiguar por qué ciertas funciones no están parcheadas). Por el momento, las únicas opciones posibles son:
[general]
debug
- Imprimir mensajes de depuracióneditor = vi
: configure el editor de texto predeterminado que se utilizará cuando Recipy necesita que escriba un mensaje. Use el bloc de notas si está en Windows, por ejemploquiet
- No imprima ningún mensajeport
: especifique el puerto para usar para la GUI[data]
file_diff_outputs
: almacene la diferencia entre la salida anterior y el nuevo archivo de salida, si existe el archivo de salida antes de ejecutar el script[database]
path = /path/to/file.json
: establezca la ruta en el archivo de la base de datos[ignored metadata]
diff
: no almacene la salida de git diff
en los metadatos para una ejecución receptoragit
: no almacene nada relacionado con Git (origen, compromiso, repositorio, etc.) en los metadatos para una ejecución receptorainput_hashes
: no calcule y almacene hashes SHA -1 de archivos de entradaoutput_hashes
: no calcule y almacene hashes SHA -1 de archivos de salida[ignored inputs]
numpy
) para instruir a Recipy que no grabe entradas de este módulo, o all
para ignorar las entradas de todos los módulos[ignored outputs]
numpy
) para instruir a Recipy que no grabe salidas de este módulo, o all
para ignorar las salidas de todos los módulos Por defecto, todos los metadatos se almacenan (es decir, no se ignoran los metadatos) y no se muestran mensajes de depuración. Un archivo .recipyrc
en el directorio actual tiene prioridad sobre el archivo ~/.recipy/recipyrc
, lo que permite que las configuraciones por proyecto se manejen fácilmente.
Nota: No se proporciona ningún archivo de configuración predeterminado con Recipy, por lo que si desea configurar cualquier cosa, necesitará crear un archivo correctamente formato usted mismo.
Cuando importe recíptica, agrega una serie de clases a sys.meta_path
. Python usan estos usos como parte del procedimiento de importación para módulos. Las clases que agregamos son clases derivadas del PatchImporter
, a menudo utilizando la interfaz más fácil proporcionada por PatchSimple
, que nos permiten envolver funciones que realizan entrada/salida en una función que llama a Recipy primero para registrar la información.
En general, la mayor parte de la complejidad está oculta en PatchImporter
y PatchSimple
(más utils.py
), por lo que el código real para envolver un módulo, como numpy
es bastante simple:
# 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' )
Se debe implementar una clase como esta para cada módulo cuya entrada/salida necesita registro. En el momento en que las siguientes funciones de entrada y salida están parcheadas:
Esta tabla enumera que la receta de módulos tiene parches para y las funciones de entrada y salida que están parcheadas.
Módulo | Funciones de entrada | Funciones de salida |
---|---|---|
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 , minc1.Minc1Image.to_filename , minc2.Minc2Image.to_filename , analyze.AnalyzeImage.to_filename , parrec.PARRECImage.to_filename , spm2analyze.Spm2AnalyzeImage.to_filename |
Sin embargo, el ejemplo de código anterior muestra lo fácil que es escribir una clase para envolver un nuevo módulo, así que no dude en enviar una solicitud de extracción para hacer que el trabajo recípico funcione con sus módulos científicos favoritos.
El marco de prueba de Recipy está en integration_test
. El marco de prueba ha sido diseñado para funcionar bajo Python 2.7+ y Python 3+. Para obtener más información, consulte el marco de prueba de receta.
El marco de prueba se ejecuta en las siguientes plataformas: