2012-08-28 6 views
5

Bir alt komutun varsayılan değerlerini geçersiz kılmak/genişletmek için global seçenekleri argparse.ArgumentParser nesnesinden kullanabilmek istiyorum.Genel seçenekler üzerinden argparse augment alt komut varsayılanları

bir örnek olur görüntülenir yardım aşağıdaki oyuncak örneğin küresel güncellemeleri, yani yansıtan be: Ben yardım modunda bu çalıştırdığınızda ben alacağı İdeal

import argparse 
import os 
import sys 

# Global parser and options. 
parser = argparse.ArgumentParser(
    formatter_class=argparse.ArgumentDefaultsHelpFormatter) 

parser.add_argument("--user", 
        dest="user", 
        default=os.environ.get("USER"), 
        help="Override the setting of the $USER variable.") 

# Sub-command parser and options. 
subparsers = parser.add_subparsers() 

command = subparsers.add_parser(
    "command", 
    formatter_class=argparse.ArgumentDefaultsHelpFormatter) 

command.add_argument("--config", 
        dest="config", 
        default="~%s/config" % os.environ.get("USER"), 
        help="The config file.") 

options = parser.parse_args() 

> python example.py --user thing command --help 
usage: example.py command [-h] [--config CONFIG] 

optional arguments: 
    -h, --help  show this help message and exit 
    --config CONFIG The config file. (default: ~thing/config) 

, yani yapılandırma dosyası yolu kullanıcıya özgüdür (şey). Varsayılan yapılandırmayı "~%(user)s/config" olarak değiştirebileceğimi ve daha sonra seçenekler ad alanıyla çalışma zamanında çözebileceğimin farkındayım, ancak yardımın daha açık olmasını istiyorum. bu biraz hacky görünüyor olsa

Ben

if "--help" in sys.argv: 

    # Parse the command minus the help to obtain the global options. 
    args = sys.argv[1:] 
    args.remove("--help") 

    # Update the defaults with the global options. 
    options = parser.parse_args(args) 
    command.set_defaults(config="~%s/config" % options.user) 

    # Re-parse the options. 
    parser.parse_args() 

, alternatif bir çözüm, küresel seçenekleri elde etmek kez argümanları ayrıştırmak yani çalışmak olacaktı toplamak. Daha iyi bir yaklaşım/çözüm var mı?

cevap

4

Genel seçenekleri tanımladıktan sonra, alt komutları tanımlamadan önce, --user değerinin ne olduğunu öğrenmek için parse_known_args numaralı telefonu arayın. Ardından, --user değerini kullanarak varsayılanını numaralı çağrıyı, parse_args numaralı çağrıyı komut satırındaki tüm seçenekleri ayrıştırmak üzere tanımlamak için subparser komutlarını tanımlamayı bitirin.

Bu alternatifinizden biraz farklıdır, ancak tüm komut satırı işlemlerini argparse nesnesinin içinde tutar.

import os 
import argparse 

# Global preparser and options. 
preparser = argparse.ArgumentParser(add_help=False) 
preparser.add_argument("--user", dest="user", default=os.environ.get("USER")) 

# ****** NEW ******* 
options, _ = preparser.parse_known_args() # Ignore what we haven't defined yet 
user = options.user      # Use this to define the default of --config 

parser = argparse.ArgumentParser(parents=[ preparser ], add_help=True, 
        formatter_class=argparse.ArgumentDefaultsHelpFormatter) 

# Sub-command parser and options. 
subparsers = parser.add_subparsers() 

command = subparsers.add_parser("command") 

# ****** MODIFIED ******* 
command.add_argument("--config", dest="config", default="~%s/config" % (user,)) 

options = parser.parse_args() 
+0

Teşekkür özelleştirilmiştir. Bu yaklaşım kesinlikle benim yaklaşımımdan çok daha temiz/yalın ve argparse olmadan denediğim bir yaklaşıma daha çok benziyor, yani argümanları iki kez ayrıştırıyor. Parse_known_args() 'ı, örneğin benim için çıkarmadan ziyade "--help" argümanı sağlandığında seçenekler (çıkmanın tersine) ile dönmek için nasıl alabileceğimi görmek için koda bakabilirim. – John

+0

Oh, bunu unuttum. 'Parse_known_args()' argümanParser.exit' ('sys.exit' etrafında nispeten ince bir sarıcı olan) 'çağırdığında atacak 'SystemExit' istisnasını yakalayabilirsiniz. – chepner

+0

Hey, evet bunu denedim, ancak try/except ile ilgili sorun, seçeneklerin tanımsız olmasıdır. – John

0

Burada zamanında, doğrudan yardım hattını değiştiren bir çözüm (Ben kodunuzu biraz sadece bu yanıt için kısaltmak için. Azaltılmakta). Ayrıca os.environ veya başka bir küresel de değiştirebilir, ancak basit tutacağım. Anahtar, bir değişkene add_argument('--config'...) tarafından oluşturulan eylemi atamaktadır. help sadece bu değişkenin bir özniteliğidir. Bunu değiştirmekte özgürsünüz. Sadece cmd -h ile çağrıldığında

class FooAction(argparse.Action): 
    def __call__(self, parser, namespace, values, option_string=None): 
     config.help = 'new user (%s)'% values 
     setattr(namespace, self.dest, values) 

parser = argparse.ArgumentParser() 
parser.add_argument('--user',action=FooAction) 
sub = parser.add_subparsers() 
cmd = sub.add_parser('cmd') 
config = cmd.add_argument('--config',help='initial help') 
config.help = 'default help' # alt way of setting 'help' 
# print config # to see other attributes of the config action 
args = parser.parse_args() 
print args 

biz --user xxx cmd -h ile çağrıldığında default help

$ python stack12167228.py cmd -h 
usage: stack12167228.py cmd [-h] [--config CONFIG] 

optional arguments: 
    -h, --help  show this help message and exit 
    --config CONFIG default help 

olsun, yardım yanıtı için

$ python stack12167228.py --user xxx cmd -h 
usage: stack12167228.py cmd [-h] [--config CONFIG] 

optional arguments: 
    -h, --help  show this help message and exit 
    --config CONFIG new user (xxx) 
İlgili konular