我想知道是否可以在jupyter / ipython笔记本中使用命令行参数填充sys.argv
(或其他一些结构),类似于它是如何完成的一个python脚本。
例如,如果我按如下方式运行python脚本:
python test.py False
然后sys.argv
将包含参数False
。但是,如果我以类似的方式运行一个jupyter笔记本:
jupyter notebook test.ipynb False
然后命令行参数丢失。有没有办法从笔记本本身访问这个参数?
答案 0 :(得分:10)
我认为这个要点可以帮助你:https://gist.github.com/gbishop/acf40b86a9bca2d571fa
这是对一个简单的参数解析器的尝试,主要是key = value对,可以在命令行和IPython笔记本中使用。它支持笔记本URL中的查询参数和笔记本的运行命令。
答案 1 :(得分:8)
我发现有两个项目可以满足您的要求
parameters
标签)以下是讨论该问题的好资源:https://github.com/jupyter/help/issues/218
答案 2 :(得分:7)
经过大量的环顾后,我发现了非常繁琐的自定义库,但是用几行代码解决了它,我认为这些代码很漂亮。我使用nbconvert最终得到一个html报告作为输出,包含笔记本中的所有图形和降价,但是通过最小的python包装器接受命令行参数:
python文件test_args.py(正常执行命令行参数):
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)
笔记本包含:
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)
我可以像往常一样解析参数运行python笔记本:
python test_args.py my_input_file --int_param 12
我倾向于将带有argparse调用的块粘贴到python包装器中,以便python脚本捕获命令行错误并且-h正常工作。
答案 3 :(得分:4)
如果目标是运行带有从命令行传递的可配置参数的笔记本,我认为最简单的方法是使用环境变量,如下所示:
NB_ARGS=some_args jupyter nbconvert --execute --to html --template full some_notebook.ipynb
然后在笔记本中,可以import os
并使用os.environ['NB_ARGS']
。例如,变量值可以是包含键值对或json的某些文本。
答案 4 :(得分:4)
在 Jupyter 单元格的顶部,放置如下一行:
%%python - --option1 value1 --option2 value2 --etc
在您的示例中:
%%python - True
这将像在命令行中一样使用提供的参数运行您的脚本。
示例:
%%python - --option1 value1 --option2 value2 --etc
import sys
if __name__ == '__main__':
print(sys.argv)
将输出:
['-', '--option1', 'value1', '--option2', 'value2', '--etc']
希望有帮助。
答案 5 :(得分:2)
如果您使用iPython进行测试,则将argparse转换为类格式可以是这样的快速虚拟解决方案。
class Args:
data = './data/penn'
model = 'LSTM'
emsize = 200
nhid = 200
args=Args()
Github page
提供网络转换服务。 http://35.192.144.192:8000/arg2cls.html
希望对您的测试有所帮助。 19年9月9日,许多错误已修复。
将argparse模块转换为类格式。需要Python3。
python3 [arg2cls.py] [argparse_script.py]
然后复制并粘贴类格式以替换argparse函数。
#!/usr/bin/env python3
from collections import OrderedDict
import sys
import re
DBG = False
#add_argument(), set_defaults() only available.
ListStartPatt = re.compile(r'\s*\[.*')
ListStartPatt2 = re.compile(r'\).*\[.*') # list out of function scope.
ListPatt = re.compile(r'(\[.*?\])')
GbgPatt = re.compile(r'(.*?)\)[^\)]+') # for float('inf') cmplx.
GbgPatt2 = re.compile(r'(.*?)\).*') # general gbg, ? for non greedy.
LpRegex = re.compile(r'\({1,}\s{0,}')
RpRegex = re.compile(r'\s{0,}\){1,}')
PrRegex = re.compile(r'\((.*)(\))(?!.*\))') # from \( to last \).
CmRegex = re.compile(r'\s{0,},\s{0,}')
StrRegex = re.compile(r'\'(.*?)\'')
# Argument dict : {arg_name : value}
argDct=OrderedDict()
# process 'default=' value.
def default_value(tval, dtype=''):
# string pattern.
regres = StrRegex.match(tval)
if regres and not re.search('int|float|long|bool|complex', dtype):
if DBG:
print('default_value: str patt found')
tval = regres.group(0)
return tval
# typed pattern.
CommaSeparated = CmRegex.split(tval)[0]
if DBG:
print('comma sepearated value:', CommaSeparated)
if ListStartPatt.match(CommaSeparated) and not ListStartPatt2.match(CommaSeparated):
lres = ListPatt.search(tval)
if lres:
tval = lres.group(1)
if DBG:
print('list patt exist tval: ', tval)
else :
tval = CmRegex.split(tval)[0]
if DBG:
print('no list format tval: ', tval)
# if default value is not like - int('inf') , remove characters after ')' garbage chars.
ires = RpRegex.split(tval)[0]
if not (re.search('int|float|long|bool|complex', ires) and re.search(r'[a-z]+\(',ires)):
if DBG:
print('not int("inf") format. Rp removed tval : ', tval)
tval = re.split(r'\s{0,}\){1,}',tval)[0]
gbg = GbgPatt2.search(tval)
if gbg:
tval = gbg.group(1)
if DBG:
print('garbage exist & removed. tval : ', tval)
# int('inf') patt.
else:
if DBG:
print('type("inf") value garbaging!')
gbg = GbgPatt.search(tval)
if gbg:
if DBG:
print('garbage found, extract!')
tval = gbg.group(1)
return tval
# Handling add_argument()
def add_argument(arg_line):
global argDct
if DBG:
print('\nin add_argument : **Pre regex: ', arg_line)
'''
argument name
'''
# 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)
# dest= keyword handling.
dest = re.search(r',\s*dest\s*=(.*)', arg_line)
if dest:
dval = dest.group(1)
dval = default_value(dval)
argname = StrRegex.search(dval)
# hyphen(-) to underscore(_)
if argname:
argname = argname.group(1).replace('-', '_')
else :
# naive str argname.
sres = StrRegex.match(arg_line)
if sres:
argname = sres.group(1)
if not argname:
return # no argument name
'''
check for syntaxes (type=, default=, required=, action=, help=, choices=)
'''
dtype = ''
dres = re.search(r',\s*type\s*=\s*(.*)', arg_line)
if dres:
dtype = dres.group(1)
dtype = CmRegex.split(dtype)[0]
dfult = re.search(r',\s*default\s*=\s*(.*)', arg_line)
rquird = re.search(r',\s*required\s*=\s*(.*)', arg_line)
action = re.search(r',\s*action\s*=\s*(.*)', arg_line)
hlp = re.search(r',\s*help\s*=\s*(.*)', arg_line)
chice = re.search(r',\s*choices\s*=\s*(.*)', arg_line)
# help message
hlp_msg = ''
if hlp:
thl = hlp.group(1)
if DBG:
print('handling help=')
hlp_msg = default_value(thl)
if hlp_msg:
hlp_msg = 'help='+hlp_msg
# choice message
choice_msg = ''
if chice:
tch = chice.group(1)
if DBG:
print('handling choices=')
choice_msg = default_value(tch)
if choice_msg:
choice_msg = 'choices='+choice_msg+' '
'''
argument value
'''
# tval: argument value.
tval = ''
# default exist.
if dfult:
tval = dfult.group(1)
tval = default_value(tval, dtype)
if DBG:
print('value determined : ', tval)
# action or required syntaxes exist.
elif action or rquird:
if DBG:
print('in action/required handling')
msg_str = ''
if action:
tval = action.group(1)
msg_str = 'action'
elif rquird:
tval = rquird.group(1)
msg_str = 'required'
tval = default_value(tval)
tval = ' ** ' + msg_str + ' '+tval+'; '+choice_msg+ hlp_msg
# no default, action, required.
else :
argDct[argname] = ' ** default not found; '+choice_msg+ hlp_msg
# value found.
if tval:
argDct[argname] = tval
# Handling set_defaults()
def set_defaults(arg_line):
global argDct
if DBG:
print('\nin set_defaults arg_line: ', arg_line)
# arguments to process.
tv=''
# arguments of set_default()
SetPatt = re.compile(r'(.+=.+\)?)')
sres = SetPatt.match(arg_line)
if sres:
tv = sres.group(1)
if DBG:
print("setPatt res: ", tv)
tv = re.sub(r'\s+','', tv)
if DBG:
print('\nset_default values: ', tv)
# one arguemnt regex.
SetArgPatt = re.compile(r',?([^=]+=)[^=,]+,?')
# handling multiple set_default() arguments. (may have a bug)
while True:
tname=''
tval =''
tnv=''
# func closed.
if re.match(r',*\).*',tv):
tv=''
break
if DBG:
print('set_default remaining: ', tv)
nres = SetArgPatt.match(tv)
if nres:
tname = nres.group(1)
if len(tv.split(tname, 1)) > 1:
tval = tv.split(tname,1)[1]
tval = default_value(tval)
tnv=tname+tval
tname = tname.rsplit('=',1)[0]
if DBG:
print('set_default tnam: ', tname)
print('set_default tval: ', tval)
if tname:
argDct[tname] = tval
# split with processed argument.
tv = tv.split(tnv)
if len(tv) > 1:
tv = tv[1]
# no more value to process
else:
break
# no arg=value pattern found.
else:
break
# 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 = list( filter(None, t) )
# remove empty line
t = [x for x in t if not re.match(r'\s{0,}\n',x)]
# concatenate multiple lined arguments.
# empl : lines to be deleted from t[].
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(r'\n{0,}','',t[i-1])
t[i-1]=re.sub(r'\s{1,}',' ',t[i-1])
empl.append(t[i])
for d in empl:
t.remove(d)
for i, line in enumerate(t):
t[i] = line.replace('\"', '\'').split('parse_args()')[0]
return t
except IOError:
print('IOError : no such file.', fname)
sys.exit()
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(r'add_argument\s*\(', arg_line):
add_argument(t)
elif re.search(r'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()
print('args=Args()')
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)
if(__name__ == "__main__"):
main()
答案 6 :(得分:0)
sys.argv
产生list
,所以我用
sys.argv.append('hello')
在jupyter笔记本中,这使我可以追加额外的成员并假装自己从命令行传递参数。
答案 7 :(得分:0)
一种解决方法是使jupyter笔记本从文件中读取参数。 在命令行中,修改文件并运行笔记本。
答案 8 :(得分:0)
我假设您只是想解析笔记本的一些参数,但是没有必要使用命令行。
如果您想解析类似的命令。
python script.py --a A --b B
您可以在笔记本中使用以下代码:
cmd = '--a A --b B'
args = args = parser.parse_args(cmd)
对于parse_args
,您可以找到更多信息here。
答案 9 :(得分:0)
一个简单而天真的解决方案是将以下代码段放在程序的第一行:
import sys
sys.argv = "your expected command line arguments here".split()
执行此命令后,argparse
之类的包将运行良好。
因此,您只需在 jupyter 实验室服务器中运行您的脚本,而无需打开终端并输入参数。
答案 10 :(得分:0)
我尝试了上面列出的答案,并想出了一个不同的解决方案。
我的原始代码是
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image")
ap.add_argument("-y", "--yolo", required=True, help="base path to YOLO directory")
ap.add_argument("-c", "--confidence", type=float, default=0.5, help="minimum probability to filter weak detections")
ap.add_argument("-t", "--threshold", type=float, default=0.3, help="threshold when applying non-maxima suppression")
args = vars(ap.parse_args())
我尝试创建一个类
Class Args():
image='photo.jpg'
yolo='yolo-coco'
confidence=0.5
threshold=0.3
args=Args()
但更多的代码片段产生了错误。
于是我在args
后面打印了vars(ap.parse_args())
,发现是一本字典。
所以只需为原始参数创建一个字典:
args={"image": 'photo.jpg', "yolo": 'yolo-coco', "confidence": 0.5,"threshold": 0.3}
答案 11 :(得分:-4)
你可以在笔记本中使用Jupyter内置魔术命令%run
。
从link开始,您可以使用:
%run -p [prof_opts] filename.py [args to program]
或类似%run -i script.py False
或者,如果要解析参数%run -i script.py --flag1 False --flag2 True