OptionParser - поддержка любого параметра в конце командной строки - PullRequest
5 голосов
/ 04 апреля 2009

Я пишу небольшую программу, которая должна выполнять команду на удаленном сервере (скажем, довольно глупая оболочка вокруг ssh [hostname] [command]).

Я хочу выполнить его так:

./floep [command] 

Однако мне нужно время от времени передавать определенные командные строки:

./floep -v [command]

поэтому я решил использовать optparse.OptionParser для этого. Проблема в том, что иногда у команды также есть аргумент, который отлично работает, если я это сделаю:

./floep -v "uname -a"

Но я также хочу, чтобы он работал, когда я использую:

./floep -v uname -a

Идея состоит в том, что, как только я столкнусь с первым аргументом без опций, все, что после этого должно стать частью моей команды.

Это, однако, дает мне:

Usage: floep [options]

floep: error: no such option: -a

Поддерживает ли OptionParser этот синтаксис? Если так: как? Если нет: как лучше это исправить?

Ответы [ 4 ]

13 голосов
/ 04 апреля 2009

Попробуйте использовать disable_interspersed_args()

#!/usr/bin/env python
from optparse import OptionParser

parser = OptionParser()
parser.disable_interspersed_args()
parser.add_option("-v", action="store_true", dest="verbose")
(options, args) = parser.parse_args()

print "Options: %s args: %s" % (options, args)

При запуске:

$ ./options.py foo -v bar
Options: {'verbose': None} args: ['foo', '-v', 'bar']
$ ./options.py -v foo  bar
Options: {'verbose': True} args: ['foo', 'bar']
$ ./options.py foo -a bar
Options: {'verbose': None} args: ['foo', '-a', 'bar']
1 голос
/ 04 апреля 2009
from optparse import OptionParser
import subprocess
import os
import sys

parser = OptionParser()
parser.add_option("-q", "--quiet",
                  action="store_true", dest="quiet", default=False,
                  help="don't print output")
parser.add_option("-s", "--signal",
                  action="store_true", dest="signal", default=False,
                  help="signal end of program and return code")

parser.disable_interspersed_args()
(options, command) = parser.parse_args()

if not command:
    parser.print_help()
    sys.exit(1)

if options.quiet:
    ret = subprocess.call(command, stdout=open(os.devnull, 'w'), 
                             stderr=subprocess.STDOUT)
else:
    ret = subprocess.call(command)

if options.signal:
    print "END OF PROGRAM!!! Code: %d" % ret
1 голос
/ 04 апреля 2009

Экземплярами OptionParser действительно можно манипулировать во время операции синтаксического анализа для сложных случаев. В этом случае, однако, я полагаю, что описанный вами сценарий поддерживается «из коробки» (что было бы хорошей новостью, если это правда! Как часто это происходит ??) См. Этот раздел в документации: Запрос и манипулирование вашим параметром анализатора .

Цитировать ссылку выше:

disable_interspersed_args ()

Установить разбор для остановки при первой не опции. Используйте это, если у вас есть Командный процессор, который запускает другую команду, которая имеет опции его и убедитесь, что эти параметры не перепутаны. Например, У каждой команды может быть свой набор параметров.

0 голосов
/ 04 апреля 2009

Вы можете использовать скрипт bash так:

#!/bin/bash
while [ "-" == "${1:0:1}" ] ; do
  if [ "-v" == "${1}" ] ; then
    # do something
    echo "-v"
  elif [ "-s" == "${1}" ] ; then
    # do something
    echo "-s"
  fi
  shift
done
${@}

$ {@} дает вам остаток командной строки, который не был использован вызовами смены. Чтобы использовать ssh, просто измените строку с $ {@} в ssh $ {user} @ $ {host} $ {@}

test.sh echo bla
бла

test.sh -v echo bla
-v
бла

test.sh -v -s echo bla
-v
-s
бла

...