Passer les arguments en ligne de commande à argv dans le carnet jupyter / ipython

je me demande s'il est possible de peupler sys.argv (ou une autre structure) avec des arguments en ligne de commande dans un ordinateur portable jupyter/ipython, similaire à la façon dont il est fait à travers un script python.

Par exemple, si je devais exécuter un script python comme suit:

python test.py False

sys.argv contiendrait l'argument False. Mais si je fais tourner un carnet jupyter de la même manière:

jupyter notebook test.ipynb False

puis l'argument de la ligne de commande se perd. Y a-t-il un moyen d'accéder à cet argument depuis le carnet lui-même?

20
demandé sur Thomas K 2016-05-31 01:39:48

4 réponses

après avoir beaucoup regardé autour de moi, j'ai trouvé des bibliothèques personnalisées très encombrantes, mais je les ai résolues avec quelques lignes de code que j'ai trouvé plutôt astucieux. J'ai utilisé nbconvert pour finir avec un rapport html en sortie qui contient tous les graphiques et markdown à partir du notebook, mais accepte les paramètres de ligne de commande tout comme toujours via un wrapper Python minimal:

le fichier python test_args.py (qui prend les paramètres de ligne de commande comme 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)

L'ordinateur portable contient:

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)

et je peux lancer python portable avec des arguments analysée comme d'habitude:

python test_args.py my_input_file --int_param 12

j'ai tendance à coller le bloc avec des appels argparse dans le paquet python pour que les erreurs de ligne de commande soient détectées par le script python et que-h fonctionne correctement.

1
répondu Steve Molly 2018-01-24 03:06:23

je pense que ce Résumé peut vous aider : https://gist.github.com/gbishop/acf40b86a9bca2d571fa

il s'agit d'une tentative d'un simple analyseur d'arguments pour la plupart des paires clé=valeur qui peuvent être utilisées à la fois sur la ligne de commande et dans les notebooks IPython. Il supporte les paramètres de requête dans les URLs de notebook et une commande D'exécution pour les notebooks.

10
répondu Spawnrider 2016-07-06 09:04:18

si vous utilisez iPython pour tester, transformer argparse en format de classe peut être une solution fictive rapide. Ce script transforme le module argparse en format de classe, de sorte que vous n'avez pas besoin de modifier le code interne. Python3 est requis.

python3 [arg2cls.py] [argparse_script.py]

puis copier et coller le format de classe pour remplacer les fonctions argparse.

#!/usr/bin/env python3
from __future__ import print_function
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 the line separated argparse 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, z in reversed(list(enumerate(t))):
        if i>0 and 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('**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 :
    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:
    # type exist
    if re.search('int|float|long|bool|complex', dtype):
      tval = dfult.group(1)
      if DBG:
        print('temp tval :' +str(tval))

      if ListPatt.search(tval):
        tval = ListPatt.search(tval).group(1)
        if DBG:
          print('-list patt : ' + str(tval))

      # if not list, use comma as separator.
      else :
        tval = CmRegex.split(tval)[0]

      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)

      if ListPatt.search(tval):
        tval = ListPatt.search(tval).group(1)

    if DBG:
      print('tval : ' + str(tval) +'\n')

  # action or required syntax exist
  elif action or rquird :
    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])

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 repo propose également une transformation rapide en ligne. http://35.192.144.192:8000/arg2cls.html

j'Espère que cela serait utile pour vos tests. mise à Jour - 20 septembre, 18 beaucoup de bugs sont corrigés.

0
répondu sngjuk 2018-10-02 15:09:24

vous pouvez utiliser Jupyter construire-dans la magie de la commande %run dans le carnet.

De cette lien, vous pouvez utiliser:

%run -p [prof_opts] filename.py [args to program]

Ou quelque chose comme %run -i script.py False

Ou si vous analysez les arguments %run -i script.py --flag1 False --flag2 True

-3
répondu mataney 2017-08-08 06:39:03