发布于 

让Python程序接收命令行参数:optparse库的使用

如何让python脚本接收到命令行的参数是压在我们不愿意做图形化界面懒狗面前的一座大山,但我也就写写小工具没做UI的必要。所以今天我去稍微了解了一下optparse这个默认库,在平时的使用场景也比较多。学前提示,这个库目前以停止更新,如果需要更多的功能可以去学习argparsse这个库。

明确目标

首先让我们假设一下,在我们本地的9000端口有一个接口,当我们去请求http://127.0.0.1:9000/hello会返回我们一个Hello World!。而我们的脚本所要完成的功能就是请求后端接口并选择是否将返回输出在命令行中。

我们分析一下可知我们应该需要一下几个参数:

  • 后端程序的IP(-i –ip)
  • 后端程序的端口(-p –port)
  • 后端程序的接口(-u –url)
  • 是否需要输出在终端中(-o –output)

我们将其转换成终端中运行时带参数的命令应该是这样的:

1
python request.py -i 127.0.0.1 -p 9000 -u /hello -o

编写代码

当我们明确了目标后我们就可以开始着手编写代码了,首先我们可以定义一个MyParse的类,在其中定义一个初始化方法__init__。定义完成后我们应该先初始化一个名为parser的对象,并设置好我们的参数。

设置参数

1
2
3
4
5
6
7
8
9
10
11
import optparse

class MyParse(object):
def __init__(self):
parser = optparse.OptionParser() # 初始化对象

#设置参数
parser.add_option("-i", "--ip", action="store", type=str, dest="ip", help="Server IP")
parser.add_option("-p", "--port", action="store", type=str, dest="port", help="Server Port")
parser.add_option("-u", "--url", action="store", type=str, dest="url", help="Server url")
parser.add_option("-o", "--output", action="store_true", dest="output", help="Print respons to screen or not")

由以上代码我们可以发现我们使用了OptionParseradd_option这两个方法,前者是用于初始化对象不带参数,非常容易理解,所以我们就只解释一下add_option这个方法。

我们分析一下第一句parser.add_option("-i", "--ip", action="store", type=str, dest="ip", help="Server IP")与最后一句parser.add_option("-o", "--output", action="store_true", dest="output", help="Print respons to screen or not")并对其进行比较。

前两个参数非常好理解是我们参数的缩写与全称。

而第三个参数action是用来表示我们参数后到底带不带值,我们-i这个参数是用来接收服务器ip的,所以毋庸质疑是需要带参数。那么store也就是次参数后必须携带值,而store_true后是不需要携带值的。

第四个参数type顾名思义也就是来标示我们接收的值的类型,在这里我们就是string类型。因为-o参数并不需要输入值所以也就可以省略去此参数,而-o参数的接收值也是bool类型的,当我们调用了此参数就为True,而不调用则为None

第五个参数dest是给参数命名,在后来我们从代码中调用参数的值也正是使用这个名称。

最后一个参数help也非常好理解,就是对我们这个参数的解释,在使用帮助命令时会被打印出来。

获取参数值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import optparse

class MyParse(object):
def __init__(self):
parser = optparse.OptionParser() # 初始化对象

# 设置参数
parser.add_option("-i", "--ip", action="store", type=str, dest="ip", help="Server IP")
parser.add_option("-p", "--port", action="store", type=str, dest="port", help="Server Port")
parser.add_option("-u", "--url", action="store", type=str, dest="url", help="Server url")
parser.add_option("-o", "--output", action="store_true", dest="output", help="Print respons to screen or not")

# 获取输入的参数
self.options, self.args = parser.parse_args()
# 输出收到的参数
print("self.options -> ",self.options)
print("self.args -> ",self.args)

if __name__ == "__main__":
my_parse = MyParser()

直接运行的结果:

1
2
3
> python request.py
self.options -> {'ip': None, 'port': None, 'url': None, 'output': None}
self.args -> []

在我们获取参数时,我们会用到两个属性optionsargs,还有一个parse_args方法。由于parse_args用法非常明了再次我们也不介绍了,就是获取接收到的值。而optionsargs就是存放我们接收到的值用的。

我们从代码的运行结果来看发现options中存放的就是参数的值,输出中Key的值就是我们定义参数时dest的值。由于我们并没有输入任何参数所以他们的Value都为None

而我们反观args中却没有任何值,那么他是用来存放什么的呢?我们再次运行程序:

1
2
3
> python request.py -i 127.0.0.1 -p 9000 -u /hello -o asdasd 123123
self.options -> {'ip': '127.0.0.1', 'port': '9000', 'url': '/hello', 'output': True}
self.args -> ['asdasd', '123123']

我们在命令后加了很多不必要的参数,而这些参数值都被存在了args中了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import optparse

class MyParse(object):
def __init__(self):
parser = optparse.OptionParser() # 初始化对象

# 设置参数
parser.add_option("-i", "--ip", action="store", type=str, dest="ip", help="Server IP")
parser.add_option("-p", "--port", action="store", type=str, dest="port", help="Server Port")
parser.add_option("-u", "--url", action="store", type=str, dest="url", help="Server url")
parser.add_option("-o", "--output", action="store_true", dest="output", help="Print respons to screen or not")

# 获取输入的参数
self.options, self.args = parser.parse_args()
# 输出收到的参数
print("self.options -> ",self.options)
print("self.args -> ",self.args)

def handle_options(self):
# print("ip: ", self.options["ip"]) # 错误写法
print("ip: ", self.options.ip) # 正确写法
print("port: ", self.options.port)

if __name__ == "__main__":
my_parse = MyParser()
my_parse.handle_options()

看到这有些同学会跑去写代码去尝试获取参数,发现直接对options用字典的方法去取值会报错。我们用type(self.option)去输出一下会发现这个根本就不是字典类型。我们如果想获取参数的值则必须使用属性的方式来获取,比如获取ip这个属性在__init__方法中就应该是self.options.ipargs则不像options,他就是一个列表,我们可以直接用self.args[0]来获取值。

使用参数值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import optparse
import requests
from datetime import datetime

class MyParse(object):
def __init__(self):
parser = optparse.OptionParser() # 初始化对象

# 设置参数
parser.add_option("-i", "--ip", action="store", type=str, dest="ip", help="Server IP")
parser.add_option("-p", "--port", action="store", type=str, dest="port", help="Server Port")
parser.add_option("-u", "--url", action="store", type=str, dest="url", help="Server url")
parser.add_option("-o", "--output", action="store_true", dest="output", help="Print respons to screen or not")

# 获取输入的参数
self.options, self.args = parser.parse_args()
# 输出收到的参数
print("self.options -> ",self.options)
print("self.args -> ",self.args)


def handle_options(self):
# print("ip: ", self.options["ip"]) # 错误写法
print("ip: ", self.options.ip) # 正确写法
print("port: ", self.options.port)


def handle_hello_world(requset_url: str, output: bool):
ret = requests.get(request_url)
if ret.ststus_code != 200:
print("请求错误")
return

curr_str = f"{str(datetime.now())} -> {ret.text}"
if output is True:
print(curr_str)


if __name__ == "__main__":
my_parse = MyParser()
# my_parse.handle_options()

# 使用my_parse对象的属性options获取用户输入的参数
ip = my_parse.options.ip
port = my_parse.options.port
url = my_parse.options.url
request_url = f"http://{ip}:{port}{url}"
output = my_parse.options.output
handle_hello_world(request_url, output)
1
2
3
4
> python request.py --ip 127.0.0.1 --port 9000 --url /hello -o
self.options -> {'ip': '127.0.0.1', 'port': '9000', 'url': '/hello', 'output': True}
self.args -> []
2022-04-17 00:59:10.015324 -> Hello World!

所使用的方法总结

方法名 作用 示例代码(取自以上代码中)
OptionParser() 初始化对象 parser = optparse.OptionParser()
add_option() 添加参数 parser.add_option(“-i”, “–ip”, action=”store”, type=str, dest=”ip”, help=”Server IP”)
parse_args() 获取参数值 self.options, self.args = parser.parse_args()