详解Python如何优雅地解析命令行

目录
  • 1. 手动解析
  • 2. getopt模块
  • 总结

如何优雅地解析命令行选项

随着我们编程经验的增长,对命令行的熟悉程度日渐加深,想来很多人会渐渐地体会到使用命令行带来的高效率。

自然而然地,我们自己写的很多程序(或者干脆就是脚本),也希望能够像原生命令和其他程序一样,通过运行时输入的参数就可以设定、改变程序的行为;而不必一层层找到相应的配置文件,然后还要定位到相应内容、修改、保存、退出……

想想就很麻烦好吗

1. 手动解析

所以让我们开始解析命令行参数吧~

在以前关于模块的文章中我们提到过sys.args这个变量,其中保存的就是调用当前脚本时传入的命令行参数。

我们先观察一下这个变量:

# test_sys.py
import sys

print(sys.argv)

通过命令行调用:

$ python test_sys.py -d today -t now --author justdopython --country China --auto

得到如下输出结果:

['test_sys.py', '-d', 'today', '-t', 'now', '--author', 'justdopython', '--country', 'China', '--auto']

可见,sys.argv其实就是将命令行参数按空格切分,得到的一个字符串列表。此外,命令行参数的第一个就是当前运行的脚本名称。

我们如果想要提取出各个参数及其对应的值,首先得区分出命令行的长参数和短参数,它们分别由“--”和“-”开头作为标识。所以我们也以此作为判断长短参数的条件:

import sys

for command_arg in sys.argv[1:]:
    if command_arg.startswith('--'):
        print("%s 为长参数" % command_arg)
    elif command_arg.startswith('-'):
        print("%s 为短参数" % command_arg)

测试结果:

$ python manually_parse_argv.py -d today -t now --author justdopython --country China --auto

-d 为短参数
-t 为短参数
--author 为长参数
--country 为长参数
--auto 为长参数

紧接着,我们需要在解析出长短参数这一步的基础上,再解析出对应的参数值:

# manually_parse_argv.py
import sys

# 由于sys.argv的第一个变量是当前脚本名称,因此略过
for index, command_arg in enumerate(sys.argv[1:]):
    if command_arg.startswith('--'):
        try:
            value = sys.argv[1:][index+1]
            if not value.startswith('-'):
                print("%s 为长参数,参数值为 %s" % (command_arg, value))
                continue
        except IndexError:
            pass

        print("%s 为长参数,无参数值" % command_arg)

    elif command_arg.startswith('-'):
        try:
            value = sys.argv[1:][index+1]
            if not value.startswith('-'):
                print("%s 为短参数,参数值为 %s" % (command_arg, value))
                continue
        except IndexError:
            pass

        print("%s 为短参数,无参数值" % command_arg)

再测试一下:

$ python manually_parse_argv.py -d today -t now --author justdopython --country China --auto

-d 为短参数,参数值为 today
-t 为短参数,参数值为 now
--author 为长参数,参数值为 justdopython
--country 为长参数,参数值为 China
--auto 为长参数,无参数值

看起来还不错。

但是再看看我们的代码……真正的逻辑还没开始,反倒是为了解析命令行参数已经写了几十行代码。这一点都不pythonic——这还不包括一些其他关于异常情况的处理。

更何况是要在每个类似的程序中加入这么一段程序了。

2. getopt模块

Python的好处就在于,生态过于丰富,几乎你要用到的每个功能,都已经有人为你写好了现成的模块以供调用。

衣来伸手饭来张口的日子除了能在梦中想想,在用Python写程序的时候也不是不可以奢望。

比如命令行参数解析,就有一个名为getopt的模块,既能够准确区分长短命令行参数,也能够恰当地提取命令行参数的值。

咱们先来看看:

# test_getopt.py
import sys
import getopt

opts, args = getopt.getopt(sys.argv[1:], 'd:t:', ["author=", "country=", "auto"])

print(opts)
print(args)

打印结果:

$ python test_getopt.py -d today -t now --author justdopython --country China --auto
[('-d', 'today'), ('-t', 'now'), ('--author', 'justdopython'), ('--country', 'China'), ('--auto', '')]
[]

下面我们来分别解释一下相关参数的含义。

getopt模块中的getopt函数用于解析命令行参数。

该函数接受三个参数:args,shortopts和longopts,分别代表“命令行参数”,“要接收的短选项”和“要接收的长选项”。

其中args和longopts均为字符串组成的列表,而shortopts则为一个字符串。

同样地,由于sys.argv的第一个值为当前脚本名称,所以多数情况下我们会选择向args参数传入sys.argv[1:]的值。

而shortopts这个参数接受的字符串则表示需要解析哪些短选项,字符串中每个字母均表示一个短选项:

import sys
import getopt

opts, args = getopt.getopt(sys.argv[1:], 'dt')

print(opts)
print(args)

输出结果:

$ python test_getopt.py -d  -t
[('-d', ''), ('-t', '')]
[]

当然,如果输入的参数少于预期,也不会导致解析失败:

$ python test_getopt.py  -t
[('-t', '')]
[]

但要是给出了预期之外的参数,就会导致模块抛错:

$ python test_getopt.py -d  -t -k
Traceback (most recent call last):
  File "test_getopt.py", line 11, in <module>
    opts, args = getopt.getopt(sys.argv[1:], 'dt')
      ...
    raise GetoptError(_('option -%s not recognized') % opt, opt)
getopt.GetoptError: option -k not recognized

这样的处理逻辑也符合我们使用命令的体验,可以简单地理解为“宁缺毋滥”。

如果短参数相应的字母后带了一个冒号:,则意味着这个参数需要指定一个参数值。getopt会将该参数对应的下一个命令行参数作为参数值(而不论下一个参数是什么形式):

import sys
import getopt

opts, args = getopt.getopt(sys.argv[1:], 'd:t')

print(opts)
print(args)

# $ python test_getopt.py -d  -t
# [('-d', '-t')]
# []

此外,一旦getopt在预期接收到长短选项的位置没有找到以“--”或“-”开头的字符串,就会终止解析过程,剩下的未解析字符串均放在返回元组的第二项中返回。

$ python test_getopt.py -d d_value o --pattern -t
[('-d', 'd_value')]
['o', '--pattern', '-t']

类似地,longopts参数表示需要解析的长参数。

列表中的每一个字符串代表一个长参数:

import sys
import getopt

opts, args = getopt.getopt(sys.argv[1:], '', ["author", "country"])

print(opts)
print(args)

# $ python test_getopt.py --author  --country
# [('--author', ''), ('--country', '')]
# []

要解析带有参数值的长参数,还应在每个长参数后附带一个等于号(=),以标识该参数需要带值:

import sys
import getopt

opts, args = getopt.getopt(sys.argv[1:], '', ["author=", "country"])

print(opts)
print(args)

# $ python test_getopt.py --author justdopython --country
# [('--author', 'justdopython'), ('--country', '')]
# []

所以最终就得到了我们一开始的解析结果:

import sys
import getopt

opts, args = getopt.getopt(sys.argv[1:], 'd:t:', ["author=", "country=", "auto"])

print(opts)
print(args)

# $ python test_getopt.py -d today -t now --author justdopython --country China --auto
# [('-d', 'today'), ('-t', 'now'), ('--author', 'justdopython'), ('--country', 'China'), ('--auto', '')]
# []

解析完成后,我们再从opts中提取相应的值即可。

懒人福音

getopt除了替我们节省了编写命令行参数解析代码的时间和精力,另一方面还可以让你在输入命令行参数时少打几个字母——当然,严谨来讲,我们并不建议此类行为。慎用,慎用!

getopt对长参数的解析支持前缀匹配,只要输入的参数能够与某个指定参数唯一匹配,同样能够完成预期解析。

$ python test_getopt.py -d today -t now --auth justdopython --coun China --auto
[('-d', 'today'), ('-t', 'now'), ('--author', 'justdopython'), ('--country', 'China'), ('--auto', '')]
[]

可以看到,author和country两个参数我们都只输入了一部分,但是getopt依然进行了正确的解析。

总结

本文讲解了使用Python解析命令行参数的两种方式,一种是略显笨重的手动解析,即自己编写程序自定义解析;另一种则是调用现成、且更加健壮的getopt模块来完成解析。

从此以后,我们终于可以摆脱繁琐的配置文件,用一种优雅简洁的方式来修改程序的行为了。

以上就是详解Python如何优雅地解析命令行的详细内容,更多关于Python解析命令行的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python命令行参数解析模块getopt使用实例

    格式 getopt(args, options[, long_options]) 1.args表示要解析的参数. 2.options表示脚本要识别的字符.字符之间用":"分隔,而且必须要以":"后结尾,例如"a:b:c:". 3.long_options是可选的,如果指定的话,可以解析长选项.形式为字符串列表,如['foo=', 'frob='].长选项要求形式为"–name=value" 4.该方法返回2个元素.第一个元素是

  • Python命令行解析器argparse详解

    目录 第1章 argparse简介 1.1 解析 1.2 argparse定义三步骤 1.3  代码示例 第2章 参数详解 2.1 创建一个命令行解析器对象:ArgumentParser() 2.2 为命令行添加参数: add_argument() 方法 2.3 解析命令行的参数:parse_args() 2.4 命令行参数的输入 2.5 命令行参数的使用 总结 第1章 argparse简介 1.1 解析 argparse 模块是 Python 内置的一个用于命令项选项与参数解析的模块,argp

  • Python 中使用 argparse 解析命令行参数

    目录 1.Python 中的参数解析 2.类型 3.子命令 4.程序架构 使用 argparse 模块为应用程序设置命令行选项. 有一些第三方库用于命令行解析,但标准库 argparse 与之相比也毫不逊色. 无需添加很多依赖,你就可以编写带有实用参数解析功能的漂亮命令行工具. 1.Python 中的参数解析 使用 argparse 解析命令行参数时,第一步是配置一个 ArgumentParser 对象.这通常在全局模块内完成,因为单单_配置_一个解析器没有副作用. import argpars

  • Python命令行解析模块详解

    本文研究的主要是Python命令行解析模块的相关内容,具体如下. Python命令行常见的解析器有两种,一是getopt模块,二是argparse模块.下面就解读下这两种解析器. getopt模块 这个模块可以帮助脚本解析命令行参数,一般是sys.argv[1:].它遵循着Unix的getopt()函数相同的约定(用-/--指定命令参数).这个模块提供两个函数(getopt.getopt()/getopt.gnu_getopt())和一个参数异常(getopt.GetoptError). 这里重

  • python解析命令行参数的三种方法详解

    这篇文章主要介绍了python解析命令行参数的三种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python解析命令行参数主要有三种方法:sys.argv.argparse解析.getopt解析 方法一:sys.argv -- 命令行执行:python test_命令行传参.py 1,2,3 1000 # test_命令行传参.py import sys def para_input(): print(len(sys.argv)) #

  • 详解Python如何优雅地解析命令行

    目录 1. 手动解析 2. getopt模块 总结 如何优雅地解析命令行选项 随着我们编程经验的增长,对命令行的熟悉程度日渐加深,想来很多人会渐渐地体会到使用命令行带来的高效率. 自然而然地,我们自己写的很多程序(或者干脆就是脚本),也希望能够像原生命令和其他程序一样,通过运行时输入的参数就可以设定.改变程序的行为:而不必一层层找到相应的配置文件,然后还要定位到相应内容.修改.保存.退出…… 想想就很麻烦好吗 1. 手动解析 所以让我们开始解析命令行参数吧~ 在以前关于模块的文章中我们提到过sy

  • 详解python中的三种命令行模块(sys.argv,argparse,click)

    Python作为一门脚本语言,经常作为脚本接受命令行传入参数,Python接受命令行参数大概有三种方式.因为在日常工作场景会经常使用到,这里对这几种方式进行总结. 命令行参数模块 这里命令行参数模块平时工作中用到最多就是这三种模块:sys.argv,argparse,click.sys.argv和argparse都是内置模块,click则是第三方模块. sys.argv模块(内置模块) 先看一个简单的示例: #!/usr/bin/python import sys def hello(name,

  • Python argparse模块实现解析命令行参数方法详解

    argparse是Python的一个标准模块,用于解析命令行参数,即解析sys.argv中定义的参数.实现在:传送门 argparse模块还会自动生成帮助和使用信息,即在最后加-h或--help.当用户输入的参数无效时,会触发error,并给出出错原因. python test_argparse.py -h python test_argparse.py --help 使用argparse的步骤: 1.创建解析器:argparse.ArgumentParser(),ArgumentParser是

  • 一文详解Python如何优雅地对数据进行分组

    假设我们有这样一种数据: data = [     ("apple", 30), ("apple", 35),     ("apple", 32), ("pear", 60),     ("pear", 32), ("pear", 60),     ("banana", 102), ("banana", 104) ] # 我们希望变成如下格式 &q

  • python 如何利用argparse解析命令行参数

    命令行参数工具是我们非常常用的工具,比如当我们做实验希望调节参数的时候,如果参数都是通过硬编码写在代码当中的话,我们每次修改参数都需要修改对应的代码和逻辑显然这不太方便.比较好的办法就是把必要的参数设置成通过命令行传入的形式,这样我们只需要在运行的时候修改参数就可以了. sys.argv 解析命令行传入参数最简单的办法就是通过sys.argv,sys.argv可以获取到我们通过命令行传入的参数. import sys print(sys.argv) 用法很简单,只需要调用sys.argv即可.a

  • 详解如何在Linux(CentOS 7)命令行模式安装VMware Tools

    本例中为在Linux(以CentOS 7为例)安装VMware Tools. 1.首先启动CentOS 7,在VMware中点击上方"VM",点击"Install VMware Tools..."(如已安装则显示"Reinstall VMware Tools..."). 2.在命令行输入"ls /dev"查看. 3.输入"mkdir /mnt/cdrom"在/mnt目录下新建一个名为cdrom的文件夹. 4

  • 详解Python使用simplejson模块解析JSON的方法

    1,Json模块介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集.JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)

  • 详解Python如何生成优雅的二维码

    目录 一.使用MyQR生成二维码 (1)模块安装 (2)生成一个图像二维码 二.使用qrcode生成二维码 (1)模块安装 (2)更准确的生成二维码 (3)读取二维码中的数据 二维码作为一种信息传递的工具,在当今社会发挥了重要作用.从手机用户登录到手机支付,生活的各个角落都能看到二维码的存在,那么我们如何自己生成一个二维码呢?如果使用Python,我们可以很快的生成一个二维码,我们可以自己定义二维码包含的信息.这些信息可以是文字.图片,也可以是网站.下面我们就来看看如何生成一个二维码. 一.使用

随机推荐