本文的目标很简单:帮助新的 Python 开发者了解一些关于命令行接口(CLI)的历史和术语,并探讨如何在 Python 中编写这些有用的程序。

最初……

首先,从 Unix 的角度谈谈命令行界面设计。

Unix 是一种计算机操作系统,也是 Linux 和 macOS(以及许多其他操作系统)的祖先。在图形用户界面之前,用户通过命令行提示符与计算机进行交互(想想如今的 Bash 环境)。在 Unix 下开发这些程序的主要语言是 C,它的功能非常强大。

因此,我们至少应该了解 C 程序的基础知识。

main
  1.    int main(int argc, char **argv)
  2.    {
  3.    ...
  4.    }
mainmain
argcargvargcargvargl

再进一步

  1. $ ./myprog foo bar -x baz
myprogargcargvargv[0]argv
  1.    argv[0] == "./myprog"
  2.    argv[1] == "foo"
  3.    argv[2] == "bar"
  4.    argv[3] == "-x"
  5.    argv[4] == "baz"
  6.    
  7.    /* 注:不是有效的 C 代码 */
argvargv
  1. include <stdio.h>
  2. /* 一个打印 argv 内容的简单 C 程序。*/
  3. int main(int argc, char **argv) {
  4. int i;
  5. for(i=0; i<argc; i++)
  6. printf("%s\n", argv[i]);
  7. }

早期对命令行标准化的尝试

-x/bin/ls -alShgetoptgetopt
  1. include <stdio.h>
  2. #include <getopt.h>
  3. #define OPTSTR "b:f:"
  4. extern char *optarg;
  5. int main(int argc, char **argv) {
  6. int opt;
  7. char *bar = NULL;
  8. char *foo = NULL;
  9. while((opt=getopt(argc, argv, OPTSTR)) != EOF)
  10. switch(opt) {
  11. case 'b':
  12. bar = optarg;
  13. break;
  14. case 'f':
  15. foo = optarg;
  16. break;
  17. case 'h':
  18. default':
  19. fprintf(stderr, "Huh? try again.");
  20. exit(-1);
  21. /* NOTREACHED */
  22. }
  23. printf("%s\n", foo ? foo : "Empty foo");
  24. printf("%s\n", bar ? bar : "Empty bar");
  25. }

就个人而言,我希望 Python 有开关,但这永远、永远不会发生。

GNU 时代

--file-format foo
-f foo

但我们正在讨论 Python?

你现在已经接触了足够多(太多?)的命令行的历史,对如何用我们最喜欢的语言来编写 CLI 有了一些背景知识。Python 在命令行解析方面给出了类似的几个选择:自己解析,自给自足(batteries-included)的方式,以及大量的第三方方式。你选择哪一种取决于你的特定情况和需求。

首先,自己解析

你可以从 sys 模块中获取程序的参数。

  1. import sys
  2. if __name__ == '__main__':
  3.    for value in sys.argv:
  4.        print(value)

自给自足

argparse
  1. from argparse import ArgumentParser
  2. if __name__ == "__main__":
  3.    argparser = ArgumentParser(description='My Cool Program')
  4.    argparser.add_argument("--foo", "-f", help="A user supplied foo")
  5.    argparser.add_argument("--bar", "-b", help="A user supplied bar")
  6.    
  7.    results = argparser.parse_args()
  8.    print(results.foo, results.bar)
--help

CLI 的现代方法

Click
  1. import click
  2. @click.command()
  3. @click.option("-f", "--foo", default="foo", help="User supplied foo.")
  4. @click.option("-b", "--bar", default="bar", help="User supplied bar.")
  5. def echo(foo, bar):
  6.     """My Cool Program
  7.    
  8.     It does stuff. Here is the documentation for it.
  9.     """
  10.     print(foo, bar)
  11.    
  12. if __name__ == "__main__":
  13.     echo()
@click.optionargparseecho
Click

但是,等等,还有更多!

ClickClickClickTyper
  1. import typer
  2. cli = typer.Typer()
  3. @cli.command()
  4. def echo(foo: str = "foo", bar: str = "bar"):
  5.     """My Cool Program
  6.    
  7.     It does stuff. Here is the documentation for it.
  8.     """
  9.     print(foo, bar)
  10.    
  11. if __name__ == "__main__":
  12.     cli()

是时候开始写一些代码了

sys.argvargparseClickTyper

最后,在 Python 中有很多用于解析命令行参数的第三方软件包。我只介绍了我喜欢或使用过的那些。你喜欢和/或使用不同的包是完全可以的,也是我们所期望的。我的建议是先从这些包开始,然后看看你最终的结果。

去写一些很酷的东西吧。

via: https://opensource.com/article/20/6/c-python-cli

本文由 LCTT 原创编译,Linux中国 荣誉推出