[英]How to read/process command line arguments?
我原来是C程序员。 我见过无数的技巧和“黑客”来阅读许多不同的 arguments。
Python 程序员有哪些方法可以做到这一点?
import sys
print("\n".join(sys.argv))
sys.argv
是一个列表,其中包含在命令行上传递给脚本的所有 arguments。 sys.argv[0]
是脚本名称。
基本上,
import sys
print(sys.argv[1:])
标准库中的规范解决方案是argparse
( docs ):
这是一个例子:
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_argument("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
args = parser.parse_args()
argparse
支持(除其他外):
(从链接复制)
argparse 模块可以处理位置和可选的 arguments,而 optparse 只能处理可选的 arguments
argparse 对于命令行界面应该是什么样子并不教条 - 支持诸如 -file 或 /file 之类的选项,以及必需的选项。 Optparse 拒绝支持这些功能,更喜欢纯粹而不是实用
argparse 生成更多信息性使用消息,包括从您的 arguments 确定的命令行用法,以及位置和可选 arguments 的帮助消息。optparse 模块需要您编写自己的用法字符串,并且无法显示位置 arguments 的帮助。
argparse 支持使用可变数量的命令行参数的操作,而 optparse 要求事先知道 arguments 的确切数量(例如 1、2 或 3)
argparse 支持分派到子命令的解析器,而 optparse 需要设置allow_interspersed_args
并手动执行解析器分派
我个人最喜欢的:
add_argument()
的类型和操作参数,而 optparse 需要破解 class 属性,如STORE_ACTIONS
或CHECK_METHODS
以获得正确的参数检查 还有argparse
stdlib 模块(stdlib 的optparse
模块的“改进”)。 argparse 简介中的示例:
# script.py
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'integers', metavar='int', type=int, choices=range(10),
nargs='+', help='an integer in the range 0..9')
parser.add_argument(
'--sum', dest='accumulate', action='store_const', const=sum,
default=max, help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args.accumulate(args.integers))
用法:
$ script.py 1 2 3 4
4
$ script.py --sum 1 2 3 4
10
如果您需要快速且不太灵活的东西
主要文件:
import sys
first_name = sys.argv[1]
last_name = sys.argv[2]
print("Hello " + first_name + " " + last_name)
然后运行python main.py James Smith
生成以下 output:
你好詹姆斯史密斯
docopt库真的很漂亮。 它从您的应用程序的用法字符串构建一个参数字典。
例如来自 docopt 自述文件:
"""Naval Fate.
Usage:
naval_fate.py ship new <name>...
naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
naval_fate.py ship shoot <x> <y>
naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
naval_fate.py (-h | --help)
naval_fate.py --version
Options:
-h --help Show this screen.
--version Show version.
--speed=<kn> Speed in knots [default: 10].
--moored Moored (anchored) mine.
--drifting Drifting mine.
"""
from docopt import docopt
if __name__ == '__main__':
arguments = docopt(__doc__, version='Naval Fate 2.0')
print(arguments)
一种方法是使用sys.argv
。 这将打印脚本名称作为第一个参数以及您传递给它的所有其他参数。
import sys
for arg in sys.argv:
print arg
#set default args as -h , if no args:
if len(sys.argv) == 1: sys.argv[1:] = ["-h"]
我自己使用 optparse,但我真的很喜欢 Simon Willison 使用他最近推出的optfunc库所采取的方向。 它的工作原理是:
“内省 function 定义(包括其 arguments 及其默认值)并使用它来构建命令行参数解析器。”
因此,例如,这个 function 定义:
def geocode(s, api_key='', geocoder='google', list_geocoders=False):
变成了这个 optparse 帮助文本:
Options:
-h, --help show this help message and exit
-l, --list-geocoders
-a API_KEY, --api-key=API_KEY
-g GEOCODER, --geocoder=GEOCODER
我喜欢 stdlib 的 getopt,例如:
try:
opts, args = getopt.getopt(sys.argv[1:], 'h', ['help'])
except getopt.GetoptError, err:
usage(err)
for opt, arg in opts:
if opt in ('-h', '--help'):
usage()
if len(args) != 1:
usage("specify thing...")
最近我一直在包装一些与此类似的东西来使事情不那么冗长(例如;使“-h”隐含)。
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args.accumulate(args.integers))
Assuming the Python code above is saved into a file called prog.py
$ python prog.py -h
Ref-link: https://docs.python.org/3.3/library/argparse.html
另一种选择是argh 。 它建立在 argparse 之上,可以让你编写如下内容:
import argh
# declaring:
def echo(text):
"Returns given word as is."
return text
def greet(name, greeting='Hello'):
"Greets the user with given name. The greeting is customizable."
return greeting + ', ' + name
# assembling:
parser = argh.ArghParser()
parser.add_commands([echo, greet])
# dispatching:
if __name__ == '__main__':
parser.dispatch()
它会自动生成帮助等,您可以使用装饰器来提供有关 arg-parsing 应该如何工作的额外指导。
您可能对我编写的一个小模块 Python 感兴趣,该模块使命令行 arguments 的处理更加容易(开源且免费使用)- Commando
我建议将docopt视为其他这些工具的简单替代品。
docopt 是一个新项目,它通过解析您的 --help 用法消息来工作,而不是要求您自己实现所有内容。 您只需要将您的使用信息放入 POSIX 格式。
同样对于 python3,您可能会发现使用扩展可迭代拆包来处理可选位置 arguments 而不需要额外的依赖性很方便:
try:
_, arg1, arg2, arg3, *_ = sys.argv + [None] * 2
except ValueError:
print("Not enough arguments", file=sys.stderr) # unhandled exception traceback is meaningful enough also
exit(-1)
上面的argv
unpack 使arg2
和arg3
“可选”——如果它们没有在argv
中指定,它们将是 None,而如果第一个没有指定,则 ValueError 将是thouwn:
Traceback (most recent call last):
File "test.py", line 3, in <module>
_, arg1, arg2, arg3, *_ = sys.argv + [None] * 2
ValueError: not enough values to unpack (expected at least 4, got 3)
import sys
# Command line arguments are stored into sys.argv
# print(sys.argv[1:])
# I used the slice [1:] to print all the elements except the first
# This because the first element of sys.argv is the program name
# So the first argument is sys.argv[1], the second is sys.argv[2] ecc
print("File name: " + sys.argv[0])
print("Arguments:")
for i in sys.argv[1:]:
print(i)
让我们将此文件命名为command_line.py
并运行它:
C:\Users\simone> python command_line.py arg1 arg2 arg3 ecc
File name: command_line.py
Arguments:
arg1
arg2
arg3
ecc
现在让我们编写一个简单的程序sum.py
:
import sys
try:
print(sum(map(float, sys.argv[1:])))
except:
print("An error has occurred")
结果:
C:\Users\simone> python sum.py 10 4 6 3
23
我们的一些生物技术客户最近提出了这两个问题:
我在下面包含了一个 Python 脚本,我相信它可以回答这两个问题。 假设以下 Python 脚本保存在文件 test.py 中:
#
#----------------------------------------------------------------------
#
# file name: test.py
#
# input values: data - location of data to be processed
# date - date data were delivered for processing
# study - name of the study where data originated
# logs - location where log files should be written
#
# macOS usage:
#
# python3 test.py "/Users/lawrence/data" "20220518" "XYZ123" "/Users/lawrence/logs"
#
# Windows usage:
#
# python test.py "D:\data" "20220518" "XYZ123" "D:\logs"
#
#----------------------------------------------------------------------
#
# import needed modules...
#
import sys
import datetime
def main(argv):
#
# print message that process is starting...
#
print("test process starting at", datetime.datetime.now().strftime("%Y%m%d %H:%M"))
#
# set local values from input values...
#
data = sys.argv[1]
date = sys.argv[2]
study = sys.argv[3]
logs = sys.argv[4]
#
# print input arguments...
#
print("data value is", data)
print("date value is", date)
print("study value is", study)
print("logs value is", logs)
#
# print message that process is ending...
#
print("test process ending at", datetime.datetime.now().strftime("%Y%m%d %H:%M"))
#
# call main() to begin processing...
#
if __name__ == '__main__':
main(sys.argv)
该脚本可以在 macOS 计算机上的终端 shell 中执行,如下所示,结果将打印到标准 output(确保当前目录包含 test.py 文件):
$ python3 test.py "/Users/lawrence/data" "20220518" "XYZ123" "/Users/lawrence/logs"
test process starting at 20220518 16:51
data value is /Users/lawrence/data
date value is 20220518
study value is XYZ123
logs value is /Users/lawrence/logs
test process ending at 20220518 16:51
该脚本也可以在 Windows 计算机上的命令提示符下执行,如下所示,结果将打印到标准 output(确保当前目录包含 test.py 文件):
D:\scripts>python test.py "D:\data" "20220518" "XYZ123" "D:\logs"
test process starting at 20220518 17:20
data value is D:\data
date value is 20220518
study value is XYZ123
logs value is D:\logs
test process ending at 20220518 17:20
该脚本回答了上面提出的两个问题,是开发将作为具有输入值的命令执行的脚本的良好起点。
这处理简单的开关,带有可选替代标志的值开关。
import sys
# [IN] argv - array of args
# [IN] switch - switch to seek
# [IN] val - expecting value
# [IN] alt - switch alternative
# returns value or True if val not expected
def parse_cmd(argv,switch,val=None,alt=None):
for idx, x in enumerate(argv):
if x == switch or x == alt:
if val:
if len(argv) > (idx+1):
if not argv[idx+1].startswith('-'):
return argv[idx+1]
else:
return True
//expecting a value for -i
i = parse_cmd(sys.argv[1:],"-i", True, "--input")
//no value needed for -p
p = parse_cmd(sys.argv[1:],"-p")
新答案的原因:
argparse
,一些答案提供了文档中的示例,一个答案表明了它的优势。 但所有人都未能充分/清楚地解释 OP 对实际问题的答案,至少对于新手而言。 argparse
的一个例子:
import argparse
def load_config(conf_file):
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser()
//Specifies one argument from the command line
//You can have any number of arguments like this
parser.add_argument("conf_file", help="configuration file for the application")
args = parser.parse_args()
config = load_config(args.conf_file)
上面的程序需要一个配置文件作为参数。 如果您提供它,它将愉快地执行。 如果没有,它将打印以下内容
usage: test.py [-h] conf_file
test.py: error: the following arguments are required: conf_file
您可以选择指定参数是否可选。
您可以使用type
键指定参数的预期类型
parser.add_argument("age", type=int, help="age of the person")
您可以通过指定default
键为 arguments 指定默认值
本文档将帮助您在一定程度上理解它。
我的解决方案是entrypoint2 。 例子:
from entrypoint2 import entrypoint
@entrypoint
def add(file, quiet=True):
''' This function writes report.
:param file: write report to FILE
:param quiet: don't print status messages to stdout
'''
print file,quiet
帮助文本:
usage: report.py [-h] [-q] [--debug] file
This function writes report.
positional arguments:
file write report to FILE
optional arguments:
-h, --help show this help message and exit
-q, --quiet don't print status messages to stdout
--debug set logging level to DEBUG
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.