Получение python argparse для использования только части значения по умолчанию в некоторых случаях - PullRequest
0 голосов
/ 03 марта 2019

Есть ли какой-нибудь простой способ получить это, чтобы он возвращал соответствующее значение по умолчанию, если в качестве аргумента сценария должно быть указано не-int или non-float значение при вызове из консоли / оболочки?

import argparse

def check(v):
    try:
        return float(v)
    except:
        #return default value for respective index in default list

parser = argparse.ArgumentParser()

parser.add_argument('-data',dest='data', type = check, nargs=5,
                    default=[-1,1,-7.9,512,0])
data = args.data
print(data)

Например, если предоставляются следующие аргументы:

file.py -data 1 6.03 1 p 1

Я бы хотел заменить только p, поэтому data напечатает [1, 6.03, 1, 512, 1].Благодаря.

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Вы можете поднять ValueError на type проверку, затем получить все аргументы с sys.argv, захватить индекс аргумента со значением non-float / non-int и заменить его значением по умолчанию для этого индекса,defaults - это диктовка со значениями по умолчанию в списке.

import argparse
import sys

def check(v):
    try:
        value = float(v)
        return value
    except ValueError:     #raise ValueError if the arg is not int           
        defaults = vars(parser.parse_args([]))   #get all the default values as a dict
        args = sys.argv[2:]         #exclude args at 0 and 1 index
        v_index = args.index(v)     #grab index at v              
        v = defaults['data'][v_index]  #assign the default value at v's index to 'v'
        return v

parser = argparse.ArgumentParser()
parser.add_argument('-data', dest='data',type = check, nargs=5, default=[-1,1,-7.9,512,0]) 
args = parser.parse_args() 
print(args.data)

Давайте проверим это сейчас с указанными вами аргументами.Мой файл называется test.py:

python test.py -data 1 6.03 1 p 1
#Output:
[1.0, 6.03, 1.0, 512, 1.0]

Позволяет добавить еще один аргумент не-int / non-float к смеси:

python test.py -data 1 6.03 x p 1
#Output:
[1.0, 6.03, -7.9, 512, 1.0]

Редактировать :Ниже приведено обобщенное решение, не зависящее от предоставленного флага ('- data', '-name'):

def check(v):
    #<--same-->
    except ValueError:             
        defaults = vars(parser.parse_args([]))   
        args = sys.argv[2:]                 
        arg_spec = str(sys.argv[1][1:]) #get the flag specified, '-name' etc.        
        v_index = args.index(v)     #grab index at v              
        v = defaults[arg_spec][v_index]  #assign the default value at v's index to 'v'
        return v

#add another flag to the arguments, 
#identify the flag passed with sys.argv, 
#convert the args passed into a dict,
#select the flag key to get its value(the args for the flag) from the dict

parser = argparse.ArgumentParser()
parser.add_argument('-data', dest='data',type = check, nargs=5, default=[-1,1,-7.9,512,0]) 
parser.add_argument('-name', dest='name',type = check, nargs=5, default=[5,20,606,81,15])
args = parser.parse_args() 
arg_spec = sys.argv[1][1:]
args_dict = vars(args)
print("The flag you provided is: '{}'. The args are: {}".format(sys.argv[1], args_dict[arg_spec]))

Некоторые тесты:

python test.py -name 1 6.03 1 x 1
#Output:
The flag you provided is: '-name'. The args are: [1.0, 6.03, 1.0, 81, 1.0]

python test.py -data 1 6.03 1 x 1
#Output:
The flag you provided is: '-data'. The args are: [1.0, 6.03, 1.0, 512, 1.0]
0 голосов
/ 03 марта 2019

Я думаю, что лучший способ - это разделить ваш аргумент 5 на 5 различных аргументов, --data1 --data2 (или даже дать более подробные имена для каждой точки данных), потому что теперь он позиционный, поэтому его трудно измеритькакой аргумент не указан. Вы также можете, как и в своем примере, передать фиктивное значение, такое как «p», а затем, когда вы анализируете свои аргументы, вы можете заменить их на свои предустановленные значения по умолчанию.

my_data = [default[i] if x == 'p' else x for i, x in enumerate(data)]

...