Python 如何从交互式解释器调用函数并为argparse传递参数?

Python 如何从交互式解释器调用函数并为argparse传递参数?,python,arguments,command,line,argparse,Python,Arguments,Command,Line,Argparse,我在文件test.py中定义了一个Python函数myFunc。我想在交互模式下从Python解释器测试这个函数,并将argparse的命令行参数传递给parse。我在Python解释器中输入testimportmyfunc的。然后我希望能够在交互模式下运行“myFunc”。。。但要传递几个命令行参数 例如,我尝试了myFunc()arg1 arg2,但是Python解释器报告了一个语法错误:无效语法 如果我只是简单地键入myFunc(),函数确实会运行,但当然没有传递任何参数 我意识到我可以在

我在文件
test.py
中定义了一个Python函数
myFunc
。我想在交互模式下从Python解释器测试这个函数,并将argparse的命令行参数传递给parse。我在Python解释器中输入testimportmyfunc的
。然后我希望能够在交互模式下运行“myFunc”。。。但要传递几个命令行参数

例如,我尝试了
myFunc()arg1 arg2
,但是Python解释器报告了一个语法错误:无效语法

如果我只是简单地键入
myFunc()
,函数确实会运行,但当然没有传递任何参数

我意识到我可以在我的代码中包含以下内容

if __name__ == "__main__":
    myFunc()
然后,我可以从命令行“python test.py arg1 arg2”运行 这确实有效

但是,我想知道是否可以在交互模式下从Python解释器测试
myFunc()
函数,并将argparse的命令行参数传递给parse

import argparse
from textwrap import dedent
import sys

def myFunc():
    print "hello!"
    print str(sys.argv)

    parser = argparse.ArgumentParser(prog='Prog',
                                     formatter_class= argparse.RawTextHelpFormatter,
                                     description = dedent('Program to control Tycon TDDin2 Relay states'))
    parser.add_argument('addr',
                        help='ip[:port] address of target device. ' \
                        'Port defaults to the snmp port of 161.')
    parser.add_argument('relay',type=str, help='name of relay')
    parser.add_argument('action', type=str, help='action = Open, Close or Cycle')
    args = parser.parse_args()

    print('args = ' + args.addr + ' ' + args.relay + ' ' + args.action)

parse_args
获取要解析的字符串列表;此参数的默认值是
sys.argv[1://code>(实际上是
None
,这将被解释为使用
sys.argv[1://code>)的请求。将相同的参数添加到
myFunc
,直接传递到
parse_args

def myFunc(cli_args=None):
    ...

    args = parser.parse_args(cli_args)
    print('args = ' + args.addr + ' ' + args.relay + ' ' + args.action)
现在,您可以使用所需的任何参数列表调用
myFunc

myFunc(["192.0.2.24", "foo", "Open"])

请记住,
parse_args
如果无法成功解析args列表(而不仅仅是引发自定义异常),则会有效地退出解释器,因此,您需要准备捕获
SystemExit
异常。

无需修改
myFunc
您可以在交互模式下修改
sys.argv
,调用函数时将对其进行解析:

sanyash@sanyash-ub16:~/myrepos/trash$ python2.7
Python 2.7.12 (default, Dec  4 2017, 14:50:18) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import file
>>> import sys
>>> sys.argv = ['./file.py', 'some addr', 'some relay', 'some action']
>>> file.myFunc()
hello!
['./file.py', 'some addr', 'some relay', 'some action']
args = some addr some relay some action
>>> 

在iTreactive
ipython
控制台会话中,我可以复制粘贴您的函数(只需做一些更改),并轻松测试它

def myFunc(argv=None):
    parser = argparse.ArgumentParser(prog='Prog',
       formatter_class= argparse.RawTextHelpFormatter,
       description = 'Program to control Tycon TDDin2 Relay states')
    parser.add_argument('addr',
                        help='ip[:port] address of target device. ' \
                        'Port defaults to the snmp port of 161.')
    parser.add_argument('relay',type=str, help='name of relay')
    parser.add_argument('action', type=str, help='action = Open, Close or Cycle')
    args = parser.parse_args(argv)
    return args
测试空命令行:

In [7]: myFunc([])                                                              
usage: Prog [-h] addr relay action
Prog: error: the following arguments are required: addr, relay, action
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2

/usr/local/lib/python3.6/dist-packages/IPython/core/interactiveshell.py:3299: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
ipython
捕获出口

myFunc()
将查看
sys.argv
;生成相同的错误消息,因为会话命令行与此解析器无关

测试帮助:

In [8]: myFunc(['-h'])                                                          
usage: Prog [-h] addr relay action

Program to control Tycon TDDin2 Relay states

positional arguments:
  addr        ip[:port] address of target device. Port defaults to the snmp port of 161.
  relay       name of relay
  action      action = Open, Close or Cycle

optional arguments:
  -h, --help  show this help message and exit
An exception has occurred, use %tb to see the full traceback.

SystemExit: 0
....
使用有效列表进行测试:

In [9]: myFunc(['testpy','arg1','arg2'])                                        
Out[9]: Namespace(action='arg2', addr='testpy', relay='arg1')

这将显示函数返回的
args
命名空间。

谢谢。。。这确实有效。我以前没有正确的调用语法。。。myFunc([“192.0.2.24”,“foo”,“Open”])这是您在捕获SystemExit异常的重要性方面提出的一个非常好的观点。您可能只需要使用monkey patch或mock
ArgumentParser。错误也可以是
。在测试期间通常不赞成全局状态的变化。@chepner,
argparse
的unittest文件通过修改
sys.argv
来测试解析器。这与真实世界中的命令行使用尽可能接近。它还通过
parse_args(alist)
进行测试。Syayas正在演示一个交互式测试,而不是一个FrimunUnTest.给定代码< >错误<代码>调用<代码> sys .EXECU/<代码>,而不是简单地引发异常,我不会考虑<代码> AgPARSE> 一个好实践的典范.