用 Python 解析命令行参数


用 Python 解析命令行参数

文章插图
 
借鉴 C 语言的历史 , 学习如何用 Python 编写有用的 CLI 程序 。
  • 来源:https://linux.cn/article-12286-1.html
  • 作者:Erik O'shaughnessy
  • 译者:Xingyu.Wang
本文的目标很简单:帮助新的 Python 开发者了解一些关于 命令行接口 (CLI)的历史和术语 , 并探讨如何在 Python 中编写这些有用的程序 。
最初……首先 , 从 Unix 的角度谈谈命令行界面设计 。
Unix 是一种计算机操作系统 , 也是 Linux 和 macOS(以及许多其他操作系统)的祖先 。在图形用户界面之前 , 用户通过命令行提示符与计算机进行交互(想想如今的 Bash 环境) 。在 Unix 下开发这些程序的主要语言是 C  , 它的 功能 非常强大 。
因此 , 我们至少应该了解 C 程序 的基础知识 。
假设你没有读过上面那个链接的内容 , C 程序的基本架构是一个叫做 main 的函数 , 它的签名是这样的 。
   int main(int argc, char **argv)   {   ...   }对于 Python 程序员来说 , 这应该不会显得太奇怪 。C 函数首先有一个返回类型、一个函数名 , 然后是括号内的类型化参数 。最后 , 函数的主体位于大括号之间 。函数名 main 是 运行时链接器 (构造和运行程序的程序)如何决定从哪里开始执行你的程序 。如果你写了一个 C 程序 , 而它没有包含一个名为 main 的函数 , 它将什么也做不了 。伤心 。
函数参数变量 argc 和 argv 共同描述了程序被调用时用户在命令行输入的字符串列表 。在典型的 Unix 命名传统中 , argc 的意思是“ 参数计数(argument count)” , argv 的意思是“ 参数向量(argument vector)” 。向量听起来比列表更酷 , 而 argl 听起来就像一个要勒死的求救声 。我们是 Unix 系统的程序员 , 我们不求救 。我们让其他人哭着求救 。
再进一步
$ ./myprog foo bar -x baz如果 myprog 是用 C 语言实现的 , 则 argc 的值是 5 , 而 argv 是一个有五个条目的字符指针数组 。(不要担心 , 如果这听起来过于技术 , 那换句话说 , 这是一个由五个字符串组成的列表 。)向量中的第一个条目 argv[0] 是程序的名称 。argv 的其余部分包含参数 。
   argv[0] == "./myprog"   argv[1] == "foo"   argv[2] == "bar"   argv[3] == "-x"   argv[4] == "baz"      /* 注:不是有效的 C 代码 */在 C 语言中 , 你有很多方法来处理 argv 中的字符串 。你可以手动地循环处理数组 argv , 并根据程序的需要解释每个字符串 。这相对来说比较简单 , 但会导致程序的接口大相径庭 , 因为不同的程序员对什么是“好”有不同的想法 。
include <stdio.h>/* 一个打印 argv 内容的简单 C 程序 。*/int main(int argc, char **argv) {    int i;       for(i=0; i<argc; i++)      printf("%sn", argv[i]);}早期对命令行标准化的尝试
命令行武器库中的下一个武器是一个叫做 getopt 的 C 标准库 函数 。这个函数允许程序员解析开关 , 即前面带破折号的参数(比如 -x) , 并且可以选择将后续参数与它们的开关配对 。想想 /bin/ls -alSh 这样的命令调用 , getopt 就是最初用来解析该参数串的函数 。使用 getopt 使命令行的解析变得相当简单 , 并改善了用户体验(UX) 。
include <stdio.h>#include <getopt.h>#define OPTSTR "b:f:"extern char *optarg;int main(int argc, char **argv) {    int opt;    char *bar = NULL;    char *foo = NULL;       while((opt=getopt(argc, argv, OPTSTR)) != EOF)       switch(opt) {          case 'b':              bar = optarg;              break;          case 'f':              foo = optarg;              break;          case 'h':          default':              fprintf(stderr, "Huh? try again.");              exit(-1);              /* NOTREACHED */       }    printf("%sn", foo ? foo : "Empty foo");    printf("%sn", bar ? bar : "Empty bar");}


推荐阅读