getopt()没有强制执行必需的参数?

时间:2011-02-18 19:46:05

标签: python

我在编写的脚本中遇到了这个getopt()代码的问题,该脚本执行了一些简单的文件操作,给出了2个必需参数(输入文件名和输出文件名)和/或2个可选/情境参数(调试或帮助)。

代码是:

def main(argv):
    try:
        opts, args = getopt.getopt(argv, "i:o:dh", ["input-file=", "output-file=", "debug", "help"])
    except getopt.GetoptError:
        usage()
        sys.exit(2)

    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()
            sys.exit()
        elif opt in ("-d", "--debug"):
            global _debug
            _debug = 1
        elif opt in ("-i", "--input-file"):
            u_input_file_name = arg
        elif opt in ("-o", "--output-file"):
            u_output_file_name = arg

根据getopt()文档:

  

需要参数后跟冒号的选项(':';即,与Unix getopt()使用的格式相同。

问题在于,根据我的理解,应该根据需要强制执行:后面的变量/ args ...但是没有强制执行选项io 。运行此代码段会在分配之前收到有关u_input_file_name被引用的错误:

[tdelane@fbsd81-1 ~/python]$ ./inco_add_cm_mpscli.py -o google
Traceback (most recent call last):
  File "./inco_add_cm_mpscli.py", line 57, in <module>
    main(sys.argv[1:])
  File "./inco_add_cm_mpscli.py", line 25, in main
    infile = open(u_input_file_name, 'r')
UnboundLocalError: local variable 'u_input_file_name' referenced before assignment

我做错了什么?

4 个答案:

答案 0 :(得分:20)

后跟冒号的选项仅表示它需要一个参数。这并不意味着强制执行该选项。您应该编写自己的代码来强制执行选项/参数。

答案 1 :(得分:4)

正如笔记一样,我发现argparse比getopt更简单,更有用,它支持必需的参数。

http://docs.python.org/2/howto/argparse.html#id1

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()

命令行

$ python prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo

答案 2 :(得分:1)

如果这对任何人都有用。这是我用来创建带有命令行选项的python脚本的样板。它处理必需的选项。如果未指定必需的选项,则脚本将终止并显示错误。

#!/usr/bin/python
import os
import sys
import getopt
import logging

  
        
# This will get the name of this file
script_name = os.path.basename(__file__)
default_loglevel = 'info'

##
# @brief Help document for this script.  See the main function below.
#
help = f'''
    {script_name} -c com_port [-o output_file] [--loglevel level]
    
    Reads the temperature data from a radio.  The temperature data is output in csv form.
    
    examples:
        Read table from radio attached to com4 and write the table to the file
        output.csv.
        
            {script_name} -c com4 -o output.csv
            
        Read table from radio attached to com3 and write the table to stdout. 
        You can use IO redirection to send the contents where every you want.
       
            # just print to the terminal 
            {script_name} -c com3
            
            # redirect to another file
            {script_name} -c com3 > somefile.csv
            
            # filter out temperatures that are -100
            {script_name} -c com3 | grep -v '^-100' 
        

    -c com_port
    --com_port comport
        Name of the COM port attached to the radio
        
    -o output_file
    --output output_file
        If specified write the table data to the given file.  If not specified
        the data will be written to stdout.
        
    --loglevel critical | error | warning | info | debug | notset
        Control the verbosity of the script by setting the log level.  Critical
        is the least verbose and notset is the most verbose.
        
        The default loglevel is {default_loglevel}.
        
        These values correspond directly to the python logging module levels. 
        (i.e. https://docs.python.org/3/howto/logging.html#logging-levels)
    
        
    -h 
    --help 
        print this message
    
'''
            
def print_help():
    print(help, file=sys.stderr)

class RequiredOptions:
    '''Just something to keep track of required options'''
    
    def __init__(self, options=[]):
        
        self.required_options = options
        
    def add(self, option):
        
        if option not in self.required_options:
            self.required_options.append(option)
            
    def resolve(self, option):
        
        if option in self.required_options:
            self.required_options.remove(option)
            
    def optionsResolved(self):
        if len(self.required_options):
            return False
        else:
            return True
        

def main(argv):
    
    # Use the logging module to print non table data.  These prints will be sent
    # to stderr.  The verbosity of the script can by adjusted via the setLevel
    # method.
    #
    logging.getLogger().setLevel(default_loglevel.upper())
    try:
        opts, args = getopt.getopt(argv,"hc:o:",["help", "com_port=", "output=","loglevel="])
    except getopt.GetoptError as e:
        print_help()
        logging.exception(e)
        sys.exit(2)
       
    # This can be overridden with the --output option. 
    #
    output_file = sys.stdout
   
    # As the required options are encountered they are removed from this list. 
    # After all of the args have been processed, require_options should be
    # empty.
    #
    required_options = RequiredOptions([ 'com_port' ])

    for opt, arg in opts:
        if opt in ('-h', '--help'):
            print_help()
            sys.exit(0)
            
        elif opt in ("-o", "--output"):
            output_file = open(arg, 'w')
        elif opt in ("-c", "--com_port"):
            com_port = arg
            required_options.resolve('com_port')
            
        elif opt in ("--loglevel"):
            # Convert to uppercase
            #
            loglevel = arg.upper()
            logging.getLogger().setLevel(loglevel)
            
        else:
            print_help()

    # Verify that all of the required options have been specified
    #
    if not required_options.optionsResolved():
        print_help()
        logging.error("The following required options were not specified:" + ' '.join(required_options.required_options))
        # indicate that there was an error by returning a non-zero value.
        #
        sys.exit(1)
    
   
    # Now do your work 
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warn message')
    logging.error('error message')
    logging.critical('critical message')
    
   

if __name__ == "__main__":
   main(sys.argv[1:])

答案 3 :(得分:0)

我只想创建像 argbit 这样的全局变量,并为每个 arg 使用按位运算而不是标志。我用过:

argbit=1

for each arg loop:
  case arg1: #mandatory
    argbit <<= 1
    do stuff and break
  case arg2: #optional
    do stuff and break

现在根据您的参数,它将左移,因此最后只需检查其值

if argbit != value:
  usage_and_exit()

如果你有两个强制参数,它的值将是 4 就像 2 ^ n。