【发布时间】:2017-03-30 10:51:14
【问题描述】:
我在 python 中使用click library 构建了一个 cli 应用程序。没有关于如何调试命令的文档。
没有click,在IDE中调试python文件很容易,但是当我们使用click时,需要通过setup.py中的console_scripts setup来运行命令。
【问题讨论】:
标签: python python-3.x python-click
我在 python 中使用click library 构建了一个 cli 应用程序。没有关于如何调试命令的文档。
没有click,在IDE中调试python文件很容易,但是当我们使用click时,需要通过setup.py中的console_scripts setup来运行命令。
【问题讨论】:
标签: python python-3.x python-click
这没有很好的记录,但您可以直接调用您的命令函数,从而可以在调试器中运行代码:
示例代码:
import click
@click.command()
@click.option('--my_arg', default=1, help='a number')
def my_command(my_arg):
click.echo("my_arg='%d'" % my_arg)
if __name__ == '__main__':
my_command(['--my_arg', '3'])
结果:
my_arg='3'
【讨论】:
sys.argv[1:],然后单击将为您完成。
我迟到了几年,但万一其他人像我一样来这里寻找答案:
使用CliRunner.invoke() 调用您的函数将返回一个带有“exc_info”属性的“Result”对象。您可以将其提供给traceback.print_exception(),如下所示:
runner = CliRunner()
result = runner.invoke(my_command)
traceback.print_exception(*result.exc_info)
【讨论】:
setup.py 生成:
来自命令行:
console_app --help
扩展到 IDE 配置 cmd:
python <absolute path to>\console_app-script.py --help
在 PyCharm 2018.2 中测试 - 您可以设置和命中断点并保留预期的 cmdline/arg 范例。
【讨论】:
我发现编写测试是调试 Click CLI 应用程序的好方法:http://click.pocoo.org/5/testing/
从你的函数和一个测试开始,然后添加它,确保测试告诉你你需要它来做什么......
另外,设置默认值也有帮助:
def run_files(input_file='/path/to/input_file', output_file='/path/to/output_file'): click.echo(input_file, output_file)
我通常还会设置日志记录并在开始时记录所有内容:
logging.basicConfig(format='%(levelname)s %(message)s', level=logging.DEBUG)
然后将这些撒在各处(IU 有带有时间戳的实用程序,但这不是必需的):
logging.info('[{0}] Blah blah selected...'.format(
utils.get_timestamp()))
您也可以使用print 或click.echo 执行此操作。
【讨论】:
你可以像这样使用pdb,把你要调试的代码放在里面:
import pdb
pdb.set_trace()
例如:
import click
@click.command()
def hello():
msg = "hi"
num = 3
import pdb
pdb.set_trace()
click.echo('Hello1!')
click.echo('Hello2!')
click.echo(msg + num)
if __name__ == '__main__':
hello()
然后就可以使用pdb了:
$ python hello.py
> /home/eduardo/w/ifpb/cozer/hello.py(11)hello()
-> click.echo('Hello1!')
(Pdb) msg
'hi'
(Pdb) num
3
(Pdb) msg = hello
(Pdb) b 13
Breakpoint 1 at /home/eduardo/w/ifpb/cozer/hello.py:13
(Pdb) c
Hello1!
Hello2!
> /home/eduardo/w/ifpb/cozer/hello.py(13)hello()
-> click.echo(msg + num)
(Pdb) c
Traceback (most recent call last):
File "hello.py", line 16, in <module>
hello()
File "/home/eduardo/w/ifpb/cozer/venv/lib/python3.5/site-packages/click/core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "/home/eduardo/w/ifpb/cozer/venv/lib/python3.5/site-packages/click/core.py", line 717, in main
rv = self.invoke(ctx)
File "/home/eduardo/w/ifpb/cozer/venv/lib/python3.5/site-packages/click/core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/eduardo/w/ifpb/cozer/venv/lib/python3.5/site-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "hello.py", line 13, in hello
click.echo(msg + num)
TypeError: unsupported operand type(s) for +: 'Command' and 'int'
报错后我们可以重试解决方法:
$ python hello.py
> /home/eduardo/w/ifpb/cozer/hello.py(11)hello()
-> click.echo('Hello1!')
(Pdb) msg
'hi'
(Pdb) num
3
(Pdb) b 13
Breakpoint 1 at /home/eduardo/w/ifpb/cozer/hello.py:13
(Pdb) c
Hello1!
Hello2!
> /home/eduardo/w/ifpb/cozer/hello.py(13)hello()
-> click.echo(msg + num)
(Pdb) num = str(num)
(Pdb) c
hi3
【讨论】:
如果您希望调试单击命令功能后执行的模块/类。
一个负担得起的解决方案是创建一个脚本来模拟执行命令后执行的流程。
然后通过将调试点放置在所需的行中,您可以实现调试功能。
这是我经过简短的网络搜索后想到的。
【讨论】: