如何读取和处理(解析)命令行参数?

2024-11-19 08:39:00
admin
原创
10
摘要:问题描述:在 Python 中,我们如何找出为脚本提供的命令行参数并处理它们?相关背景阅读:“sys.argv[1]”是什么意思?(什么是 sys.argv,它来自哪里?)。有关更具体的示例,请参阅实现“[命令] [操作] [参数]”样式的命令行界面?和如何使用 Python 的 optparse 格式化位置...

问题描述:

在 Python 中,我们如何找出为脚本提供的命令行参数并处理它们?


相关背景阅读:“sys.argv[1]”是什么意思?(什么是 sys.argv,它来自哪里?)。有关更具体的示例,请参阅实现“[命令] [操作] [参数]”样式的命令行界面?和如何使用 Python 的 optparse 格式化位置参数帮助?。


解决方案 1:

import sys

print("
".join(sys.argv))

sys.argv是一个包含命令行上传递给脚本的所有参数的列表。sys.argv[0]是脚本名称。

基本上,

import sys

print(sys.argv[1:])

解决方案 2:

标准库中的规范解决方案是argparse(文档):

以下是一个例子:

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支持(除其他外):

  • 多个选项可按任意顺序排列。

  • 短期和长期选择。

  • 默认值。

  • 生成使用帮助信息。

解决方案 3:

只是到处宣传argparse,它因为以下原因而更好。本质上:

(从链接复制)

  • argparse 模块可以处理位置参数和可选参数,而 optparse 只能处理可选参数

  • argparse 并不教条地规定你的命令行界面应该是什么样子 - 支持 -file 或 /file 等选项,以及必需选项。Optparse 拒绝支持这些功能,更喜欢纯粹性而不是实用性

  • argparse 生成更多信息丰富的使用信息,包括根据您的参数确定的命令行使用信息,以及位置参数和可选参数的帮助信息。optparse 模块要求您编写自己的使用字符串,并且无法显示位置参数的帮助。

  • argparse 支持使用可变数量的命令行参数的操作,而 optparse 要求提前知道确切的参数数量(例如 1、2 或 3)

  • argparse 支持分派到子命令的解析器,而 optparse 需要
    allow_interspersed_args手动设置和执行解析器分派

我个人最喜欢的是:

  • argparse 允许使用简单的可调用函数指定类型和操作参数add_argument()
    ,而 optparse 需要破解类属性(如

STORE_ACTIONS或)CHECK_METHODS才能获得正确的参数检查

解决方案 4:

还有argparsestdlib 模块(对 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

解决方案 5:

如果你需要快速且不太灵活的东西

主要文件:

import sys

first_name = sys.argv[1]
last_name = sys.argv[2]
print("Hello " + first_name + " " + last_name)

然后运行python main.py James Smith

产生以下输出:

你好詹姆斯史密斯

解决方案 6:

其中一种方法是使用sys.argv。这将打印脚本名称作为第一个参数以及传递给它的所有其他参数。

import sys

for arg in sys.argv:
    print arg

解决方案 7:

docopt库确实很巧妙。它根据应用程序的使用字符串构建参数字典。

例如来自 docopt readme:

"""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)

解决方案 8:

#set default args as -h , if no args:
if len(sys.argv) == 1: sys.argv[1:] = ["-h"]

解决方案 9:

我自己使用 optparse,但我非常喜欢 Simon Willison 最近推出的optfunc库。它的工作原理如下:

“自省函数定义(包括其参数及其默认值)并使用它来构建命令行参数解析器。”

例如,这个函数定义:

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

解决方案 10:

我喜欢 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”隐含)。

解决方案 11:

Pocoo 的点击更直观,需要的样板更少,并且至少与 argparse 一样强大。

到目前为止我遇到的唯一缺点是您无法对帮助页面进行太多定制,但这通常不是必需的,而docopt似乎是明智的选择。

解决方案 12:

正如您所看到的optparse “optparse 模块已弃用,不会进一步开发;argparse模块将继续开发。”

解决方案 13:

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

解决方案 14:

您可能对我编写的一个小 Python 模块感兴趣,它可以使命令行参数的处理更加容易(开源且免费使用) - Commando

解决方案 15:

另一个选项是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()

它将自动生成帮助等,并且您可以使用装饰器来提供有关参数解析如何工作的额外指导。

解决方案 16:

新答案的原因:

  1. 现有的答案指定了多个选项。

  2. 标准选项是使用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您可以通过指定键来指定参数的默认值

本文档将在一定程度上帮助您理解它。

解决方案 17:

我建议将docopt视为这些工具的简单替代方案。

docopt 是一个新项目,它通过解析您的 --help 使用信息来工作,而不需要您自己实现一切。您只需将使用信息置于 POSIX 格式中即可。

解决方案 18:

此外,使用 python3 时,您可能会发现使用扩展可迭代解包来处理可选位置参数而无需其他依赖项非常方便:

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解包使得arg2和成为arg3“可选” - 如果在中没有指定它们argv,它们将为 None,而如果没有指定第一个,则会出现 ValueError :

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)

解决方案 19:

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:Userssimone> 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:Userssimone> python sum.py 10 4 6 3
23

解决方案 20:

我的解决方案是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

解决方案 21:

这处理简单开关、带有可选替代标志的值开关。

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")

解决方案 22:

我们的几位生物技术客户最近提出了以下两个问题:

  • 我们如何将 Python 脚本作为命令执行?

  • 当 Python 脚本作为命令执行时,我们如何将输入值传递给它?

我在下面附上了一个我认为可以回答这两个问题的 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 中执行,如下所示,结果将打印到标准输出(确保当前目录包含 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 计算机上的命令提示符中执行,如下所示,结果将打印到标准输出(确保当前目录包含 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

该脚本回答了上面提出的两个问题,是开发作为带有输入值的命令执行的脚本的一个很好的起点。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用