【问题标题】:how to debug python click cli application?如何调试 python click cli 应用程序?
【发布时间】: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


    【解决方案1】:

    这没有很好的记录,但您可以直接调用您的命令函数,从而可以在调试器中运行代码:

    示例代码:

    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'
    

    【讨论】:

    • 如何传递多个参数?特别是如果其中一个是一面旗帜?如果还有另一个@click.option("--full", is_flag=True)。将它传递给 my_command 的正确语法是什么?如果我用 ["--full", True] 添加另一个数组,则执行失败。我需要这个来调试。
    • 这只是一个列表。基本上,想像 cmdlinestr.split()
    • 斯蒂芬,谢谢! Lint 抱怨缺少第二个参数,这是一种误导,但它有效!
    • 如果点击应用程序使用子命令和其他高级模式,这个调用是否仍然微不足道?在 IDE 中进行调试的需求与开发重要的应用程序相关。
    • @blamblam,这是测试代码。在这里完成要好得多...此外,在实际程序中,您可以完全关闭sys.argv[1:],然后单击将为您完成。
    【解决方案2】:

    我迟到了几年,但万一其他人像我一样来这里寻找答案:

    使用CliRunner.invoke() 调用您的函数将返回一个带有“exc_info”属性的“Result”对象。您可以将其提供给traceback.print_exception(),如下所示:

    runner = CliRunner()
    result = runner.invoke(my_command)
    traceback.print_exception(*result.exc_info)
    

    【讨论】:

      【解决方案3】:

      setup.py 生成:

      • console_script.exe
      • console_script-script.py

      来自命令行:

      console_app --help
      

      扩展到 IDE 配置 cmd:

      python <absolute path to>\console_app-script.py --help
      

      在 PyCharm 2018.2 中测试 - 您可以设置和命中断点并保留预期的 cmdline/arg 范例。

      【讨论】:

        【解决方案4】:

        我发现编写测试是调试 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()))
        

        您也可以使用printclick.echo 执行此操作。

        【讨论】:

          【解决方案5】:

          你可以像这样使用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
          

          【讨论】:

            【解决方案6】:

            如果您希望调试单击命令功能后执行的模块/类。

            一个负担得起的解决方案是创建一个脚本来模拟执行命令后执行的流程。

            然后通过将调试点放置在所需的行中,您可以实现调试功能。

            这是我经过简短的网络搜索后想到的。

            【讨论】:

            • 您是否介意提供一些代码示例来展示这实际上是多么的琐碎和实惠?
            猜你喜欢
            • 1970-01-01
            • 2017-01-13
            • 1970-01-01
            • 1970-01-01
            • 2017-04-24
            • 1970-01-01
            • 2017-07-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多