python - magic - anaconda
Pasando argumentos de lĂnea de comando a argv en jupyter/ipython notebook (5)
Me pregunto si es posible rellenar sys.argv
(o alguna otra estructura) con argumentos de línea de comandos en un cuaderno jupyter / ipython, de forma similar a como se hace a través de un script de python.
Por ejemplo, si tuviera que ejecutar un script de python de la siguiente manera:
python test.py False
Entonces sys.argv
contendría el argumento False
. Pero si ejecuto un cuaderno jupyter de una manera similar:
jupyter notebook test.ipynb False
Entonces el argumento de la línea de comando se pierde. ¿Hay alguna forma de acceder a este argumento desde el propio cuaderno?
Creo que este Gist puede ayudarte: https://gist.github.com/gbishop/acf40b86a9bca2d571fa
Este es un intento de un analizador de argumentos simple para la mayoría de los pares clave = valor que se pueden usar tanto en la línea de comandos como en los cuadernos IPython. Admite los parámetros de consulta en las direcciones URL de los blocs de notas y el comando Ejecutar para blocs de notas.
Después de mirar mucho a mi alrededor, encontré bibliotecas muy complicadas y personalizadas, pero lo resolví con unas pocas líneas de código que me parecieron bastante hábiles. Usé nbconvert para terminar con un informe html como salida que contiene todos los gráficos y la reducción del cuaderno, pero acepta los parámetros de la línea de comandos como siempre a través de un envoltorio de python mínimo:
El archivo python test_args.py (que toma los parámetros de la línea de comandos como normal):
import sys,os
IPYNB_FILENAME = ''test_argv.ipynb''
CONFIG_FILENAME = ''.config_ipynb''
def main(argv):
with open(CONFIG_FILENAME,''w'') as f:
f.write('' ''.join(argv))
os.system(''jupyter nbconvert --execute {:s} --to html''.format(IPYNB_FILENAME))
return None
if __name__ == ''__main__'':
main(sys.argv)
El cuaderno contiene:
import sys,os,argparse
from IPython.display import HTML
CONFIG_FILE = ''.config_ipynb''
if os.path.isfile(CONFIG_FILE):
with open(CONFIG_FILE) as f:
sys.argv = f.read().split()
else:
sys.argv = [''test_args.py'', ''input_file'', ''--int_param'', ''12'']
parser = argparse.ArgumentParser()
parser.add_argument("input_file",help="Input image, directory, or npy.")
parser.add_argument("--int_param", type=int, default=4, help="an optional integer parameter.")
args = parser.parse_args()
p = args.int_param
print(args.input_file,p)
y puedo ejecutar el cuaderno de Python con los argumentos analizados como de costumbre:
python test_args.py my_input_file --int_param 12
Tiendo a pegar el bloque con llamadas argparse en el envoltorio de python para que el script de python detecte los errores de la línea de comandos y -h funcione correctamente.
Hay dos proyectos que he encontrado que hacen lo que pides
- Papermill , agregará una celda a su cuaderno con los argumentos que le pase en la línea de comandos. Así que esto es bastante sencillo, usted define sus valores predeterminados en la primera celda (la etiqueta debería tener
parameters
) - nbparameterise es un concepto similar, pero no etiqueta su celda con valores predeterminados, tiene que ser el primero.
Aquí hay un buen recurso para analizar el problema: https://github.com/jupyter/help/issues/218
Si usa iPython para realizar pruebas, transformar argparse en un formato de clase puede ser una solución rápida. Este script transforma el módulo argparse en un formato de clase, por lo que no es necesario editar el código interno. Se requiere Python3.
python3 [arg2cls.py] [argparse_script.py]
luego copie y pegue el formato de clase para reemplazar las funciones argparse.
#!/usr/bin/env python3
from collections import OrderedDict
import sys
import re
DBG = False
#add_argument, set_defaults only available.
ListPatt = re.compile(''(/[.*?/])'')
GbgPatt = re.compile(''(.*)/)[A-z0-9*]'')
LpRegex = re.compile(''/({1,}/s{0,}'')
RpRegex = re.compile(''/s{0,}/){1,}'')
PrRegex = re.compile(''/((.*)(/))(?!.*/))'') # from /( to last /)
CmRegex = re.compile(''/s{0,},/s{0,}'')
StrRegex = re.compile(''/'(.*?)/''')
# Argument dict : store {arg_name : value}
argDct=OrderedDict()
# Remove empty line & Concatenate line-separated syntax.
def preprocess(fname):
try :
with open(fname, ''r'', encoding=''UTF8'') as f:
txt = f.read()
t = txt.splitlines(True)
t = str_list = list( filter(None, t) )
# remove empty line
t = [x for x in t if not re.match(''/s{0,}/n'',x)]
# concatenate multiple lined arguments.
empl = []
for i in range(len(t)-1, 0, -1):
if not re.search(''add_argument|set_defaults'', t[i]):
t[i-1] += t[i]
t[i-1]=re.sub(''/s{0,}/n{0,}/s{0,}'','''',t[i-1])
empl.append(t[i])
for d in empl:
t.remove(d)
for i, line in enumerate(t):
t[i] = line.replace(''/"'', ''/''')
return t
except IOError:
print(''IOError : no such file.'', fname)
# Handling add_argument()
def add_argument(arg_line):
global argDct
arg_line = arg_line
if DBG:
print(''in add_argument : **Pr regex : '' + str(arg_line))
#argname = DdRegex.split(arg_line)[1] # Dash or regex for arg name.
argname = re.search(''/'--(.*?)/''',arg_line)
if not argname:
argname = re.search(''/'-+(.*?)/''',arg_line)
if argname:
argname = argname.group(1).replace(''-'', ''_'')
else :
argname = StrRegex.search(arg_line).group(1)
if not argname:
return # no argument name
argDct[argname]=''''
dtype = re.search('',/s*type/s*=(.*)'', arg_line)
if dtype:
dtype = dtype.group(1)
dtype = CmRegex.split(dtype)[0]
else :
dtype = ''''
dfult = re.search('',/s*default/s*=(.*)'',arg_line)
rquird = re.search('',/s*required/s*=(.*)'',arg_line)
action = re.search('',/s*action/s*=(.*)'',arg_line)
tval = ''''
if dfult:
if DBG:
print(''in default ext'')
# type exist
if re.search(''int|float|long|bool|complex'', dtype):
tval = dfult.group(1)
if DBG:
print(''type exist tval :'' +str(tval))
if ListPatt.search(tval):
tval = ListPatt.search(tval).group(1)
if DBG:
print(''list exit-list patt : '' + str(tval))
# if not list, use comma as separator.
else :
tval = CmRegex.split(tval)[0]
if DBG:
print(''not list tval :'' +str(tval))
if not re.search(''int|float|long|bool|complex'', tval) and not LpRegex.search(tval):
tval = re.split(''/s{0,}/){1,}'',tval)[0]
gbg = re.search(GbgPatt, tval)
if gbg:
tval = gbg.group(1)
# type not specified str() assumed.
else:
tval = dfult.group(1)
regres = StrRegex.match(tval)
if regres:
tval = regres.group(0)
elif ListPatt.search(tval):
tval = ListPatt.search(tval).group(1)
else:
tval = CmRegex.split(tval)[0]
if DBG:
print(''tval : '' + str(tval) +''/n'')
# action or required syntax exist
elif action or rquird :
if DBG:
print(''in action handling'')
msg_str = ''''
if action:
tval = action.group(1)
msg_str = ''action''
else :
tval = rquird.group(1)
msg_str = ''required''
regres = StrRegex.search(tval)
if regres:
tval = regres.group(0)
else :
tval = CmRegex.split(tval)[0]
tval = ''## '' + msg_str + '' '' + tval + '' ##''
else :
argDct[argname] = ''## default None ##''
if tval:
argDct[argname] = tval
# Handling set_default()
def set_defaults(arg_line):
global argDct
if DBG:
print(''Set_defaults : '' + str(arg_line))
dfult = re.split(''/s{0,}=/s{0,}'', arg_line)
tn = dfult[0] # arg name
tv = RpRegex.split(dfult[1])[0] #arg value
argDct[tn]=tv
def transform(fname):
# t : list() contains add_argument|set_defaults lines.
arg_line_list = preprocess(fname)
for i, arg_line in enumerate(arg_line_list):
t = PrRegex.search(arg_line)
if t:
t = t.group(1) # t: content of add_argument Parentheses.
else :
continue # nothing to parse.
if re.search(''add_argument/s*/('', arg_line):
add_argument(t)
elif re.search(''set_defaults/s*/('',arg_line):
set_defaults(t)
else :
# Nothing to parse.
continue
print(''/nclass args:'')
for i in argDct:
print('' '',i, ''='', argDct[i])
print()
def main():
if len(sys.argv) <2:
print(''Usage : python arg2cls.py [target.py] [target2.py(optional)] ...'')
sys.exit(0)
sys.argv.pop(0)
#handling multiple file input.
for fname in sys.argv:
transform(fname)
# TODO : choices=, multiple keywords occurence fix.
if(__name__ == "__main__"):
main()
Github page repo también ofrece una rápida transformación en línea. http://35.192.144.192:8000/arg2cls.html
Espero que sea útil para su prueba. Actualizado - 8 de noviembre, 18 muchos errores son corregidos.
puede usar el comando mágico incorporado Jupyter %run
dentro del cuaderno.
Desde este link , puede utilizar:
%run -p [prof_opts] filename.py [args to program]
O algo así como %run -i script.py False
O si está analizando los argumentos %run -i script.py --flag1 False --flag2 True