optparse — Analisador sintático para opções de linha de comando

Código-fonte: Lib/optparse.py

Obsoleto desde a versão 3.2: O módulo optparse está suavemente descontinuado e não será mais desenvolvido; o desenvolvimento continuará com o módulo argparse.


optparse é uma biblioteca mais conveniente, flexível e poderosa para analisar opções de linha de comando do que o antigo módulo getopt. optparse usa um estilo mais declarativo de análise de linha de comando: você cria uma instância de OptionParser, preenche-a com opções e analisa a linha de comando. optparse permite que os usuários especifiquem opções na sintaxe convencional GNU/POSIX e, adicionalmente, gera mensagens de uso e ajuda para você.

Aqui está um exemplo de uso de optparse em um script simples:

from optparse import OptionParser
...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
                  help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="don't print status messages to stdout")

(options, args) = parser.parse_args()

Com essas poucas linhas de código, os usuários do seu script agora podem fazer “coisas comuns” na linha de comando, por exemplo:

<seuscript> --file=outfile -q

Ao analisar a linha de comando, optparse define atributos do objeto options retornado por parse_args() com base nos valores de linha de comando fornecidos pelo usuário. Quando parse_args() retorna da análise desta linha de comando, options.filename será "outfile" e options.verbose será False. optparse provê as opções longas e curtas, permite que opções curtas sejam mescladas e permite que opções sejam associadas a seus argumentos de várias maneiras. Portanto, as seguintes linhas de comando são todas equivalentes ao exemplo acima:

<seuscript> -f outfile --quiet
<seuscript> --quiet --file outfile
<seuscript> -q -foutfile
<seuscript> -qfoutfile

Além disso, os usuários podem executar um dos seguintes:

<seuscript> -h
<seuscript> --help

e optparse vai exibir um breve resumo das opções do seu script:

Usage: <seuscript> [options]

Options:
  -h, --help            show this help message and exit
  -f FILE, --file=FILE  write report to FILE
  -q, --quiet           don't print status messages to stdout

onde o valor de seuscript é determinado em tempo de execução (normalmente de sys.argv[0]).

Contexto

optparse foi explicitamente projetado para encorajar a criação de programas com interfaces de linha de comando diretas e convencionais. Para esse fim, ele provê apenas a sintaxe e a semântica de linha de comando mais comuns convencionalmente usadas no Unix. Se você não estiver familiarizado com essas convenções, leia esta seção para se familiarizar com elas.

Terminologia

argumento

uma string inserida na linha de comando e passada pelo shell para execl() ou execv(). Em Python, argumentos são elementos de sys.argv[1:] (sys.argv[0] é o nome do programa que está sendo executado). Shells Unix também usam o termo “word”.

Ocasionalmente, é desejável substituir uma lista de argumentos diferente de sys.argv[1:], então você deve ler “argumento” como “um elemento de sys.argv[1:], ou de alguma outra lista fornecida como um substituto para sys.argv[1:]”.

opção

um argumento usado para fornecer informações extras para guiar ou personalizar a execução de um programa. Existem muitas sintaxes diferentes para opções; a sintaxe tradicional do Unix é um hífen (“-”) seguido por uma única letra, por exemplo, -x ou -F. Além disso, a sintaxe tradicional do Unix permite que várias opções sejam mescladas em um único argumento, por exemplo, -x -F é equivalente a -xF. O projeto GNU introduziu -- seguido por uma série de palavras separadas por hífen, por exemplo, --file ou --dry-run. Essas são as únicas duas sintaxes de opção fornecidas por optparse.

Algumas outras sintaxes de opções que o mundo viu incluem:

  • um hífen seguido por algumas letras, por exemplo -pf (isso não é o mesmo que várias opções mescladas em um único argumento)

  • um hífen seguido por uma palavra completa, por exemplo -file (isso é tecnicamente equivalente à sintaxe anterior, mas eles geralmente não são vistos no mesmo programa)

  • um sinal de mais seguido por uma única letra, ou algumas letras, ou uma palavra, por exemplo +f, +rgb

  • uma barra seguida de uma letra, ou algumas letras, ou uma palavra, por exemplo /f, /file

Essas sintaxes de opção não são suportadas por optparse, e nunca serão. Isso é proposital: as três primeiras não são padrão em nenhum ambiente, e a última só faz sentido se você estiver mirando exclusivamente no Windows ou em certas plataformas legadas (por exemplo, VMS, MS-DOS).

argumento de opção

um argumento que segue uma opção, está intimamente associado a essa opção e é consumido da lista de argumentos quando essa opção é. Com optparse, os argumentos de opção podem estar em um argumento separado de sua opção:

-f foo
--file foo

ou incluídos no mesmo argumento:

-ffoo
--file=foo

Normalmente, uma opção dada ou aceita um argumento ou não. Muitas pessoas querem um recurso de “argumentos opcionais de opção”, o que significa que algumas opções aceitarão um argumento se o virem, e não aceitarão se não o virem. Isso é um tanto controverso, porque torna a análise ambígua: se -a aceita um argumento opcional e -b é outra opção inteiramente diferente, como interpretamos -ab? Por causa dessa ambiguidade, optparse não provê esse recurso.

argumento posicional

algo que sobrou na lista de argumentos depois que as opções foram analisadas, ou seja, depois que as opções e seus argumentos foram analisados ​​e removidos da lista de argumentos.

opção obrigatória

uma opção que deve ser fornecida na linha de comando; observe que a frase “opção obrigatória” é autocontraditória em inglês. optparse não impede que você implemente opções obrigatórias, mas também não ajuda muito nisso.

Por exemplo, considere esta linha de comando hipotética:

prog -v --report report.txt foo bar

-v e --report são ambas opções. Supondo que --report receba um argumento, report.txt é um argumento de opção. foo e bar são argumentos posicionais.

Para que servem as opções?

As opções são usadas para fornecer informações extras para ajustar ou personalizar a execução de um programa. Caso não tenha ficado claro, as opções geralmente são opcionais. Um programa deve ser capaz de executar muito bem sem nenhuma opção. (Escolha um programa aleatório dos conjuntos de ferramentas Unix ou GNU. Ele pode ser executado sem nenhuma opção e ainda fazer sentido? As principais exceções são find, tar e dd — todos eles são mutantes excêntricos que foram corretamente criticados por sua sintaxe não padrão e interfaces confusas.)

Muitas pessoas querem que seus programas tenham “opções obrigatórias”. Pense nisso. Se é obrigatório, então não é opcional! Se há uma informação que seu programa absolutamente requer para ser executado com sucesso, é para isso que servem os argumentos posicionais.

Como um exemplo de bom design de interface de linha de comando, considere o humilde utilitário cp, para copiar arquivos. Não faz muito sentido tentar copiar arquivos sem fornecer um destino e pelo menos uma fonte. Portanto, cp falha se você executá-lo sem argumentos. No entanto, ele tem uma sintaxe flexível e útil que não requer nenhuma opção:

cp ORIGEM DESTINO
cp ORIGEM ... DIRETÓRIO

Você pode ir bem longe só com isso. A maioria das implementações de cp fornece um monte de opções para ajustar exatamente como os arquivos são copiados: você pode preservar o modo e o tempo de modificação, evitar seguir links simbólicos, perguntar antes de destruir arquivos existentes, etc. Mas nada disso distrai da missão principal de cp, que é copiar um arquivo para outro, ou vários arquivos para outro diretório.

Para que servem os argumentos posicionais?

Argumentos posicionais são para aquelas informações que seu programa absolutamente e positivamente requer para ser executado.

Uma boa interface de usuário deve ter o mínimo de requisitos absolutos possível. Se seu programa requer 17 informações distintas para ser executado com sucesso, não importa muito como você obtém essas informações do usuário — a maioria das pessoas desistirá e irá embora antes de executar o programa com sucesso. Isso se aplica se a interface de usuário for uma linha de comando, um arquivo de configuração ou uma GUI: se você fizer tantas exigências aos seus usuários, a maioria deles simplesmente desistirá.

Em resumo, tente minimizar a quantidade de informações que os usuários são absolutamente obrigados a fornecer — use padrões sensatos sempre que possível. Claro, você também quer tornar seus programas razoavelmente flexíveis. É para isso que servem as opções. Novamente, não importa se são entradas em um arquivo de configuração, widgets no diálogo “Preferências” de uma GUI ou opções de linha de comando — quanto mais opções você implementar, mais flexível será seu programa e mais complicada se tornará sua implementação. Muita flexibilidade também tem desvantagens, é claro; muitas opções podem sobrecarregar os usuários e tornar seu código muito mais difícil de manter.

Tutorial

Embora optparse seja bastante flexível e poderoso, ele também é simples de usar na maioria dos casos. Esta seção abrange os padrões de código que são comuns a qualquer programa baseado em optparse.

Primeiro, você precisa importar a classe OptionParser; então, no início do programa principal, crie uma instância de OptionParser:

from optparse import OptionParser
...
parser = OptionParser()

Então você pode começar a definir opções. A sintaxe básica é:

parser.add_option(opt_str, ...,
                  attr=value, ...)

Cada opção tem uma ou mais strings de opção, como -f ou --file, e vários atributos de opção que informam ao optparse o que esperar e o que fazer quando encontrar essa opção na linha de comando.

Normalmente, cada opção terá uma sequência de opções curta e uma sequência de opções longa, por exemplo:

parser.add_option("-f", "--file", ...)

Você tem a liberdade de definir quantas strings de opções curtas e longas quiser (incluindo zero), desde que haja pelo menos uma string de opção no geral.

As strings de opção passadas para OptionParser.add_option() são efetivamente rótulos para a opção definida por essa chamada. Para resumir, frequentemente nos referiremos a encontrar uma opção na linha de comando; na realidade, optparse encontra strings de opção e procura opções a partir delas.

Depois que todas as suas opções estiverem definidas, instrua optparse para analisar a linha de comando do seu programa:

(options, args) = parser.parse_args()

(Se desejar, você pode passar uma lista de argumentos personalizada para parse_args(), mas isso raramente é necessário: por padrão, ele usa sys.argv[1:].)

parse_args() retorna dois valores:

  • options, um objeto que contém valores para todas as suas opções — por exemplo, se --file receber um único argumento de string, então options.file será o nome do arquivo fornecido pelo usuário, ou None se o usuário não forneceu essa opção

  • args, a lista de argumentos posicionais restantes após a análise de opções

Esta seção do tutorial abrange apenas os quatro atributos de opção mais importantes: action, type, dest (destino) e help. Destes, action é o mais fundamental.

Compreendendo as ações de opções

Ações dizem ao optparse o que fazer quando ele encontra uma opção na linha de comando. Há um conjunto fixo de ações codificadas em optparse; adicionar novas ações é um tópico avançado abordado na seção Estendendo optparse. A maioria das ações diz ao optparse para armazenar um valor em alguma variável — por exemplo, pegue uma string da linha de comando e armazene-a em um atributo de options.

Se você não especificar uma ação de opção, optparse assumirá como padrão store.

A ação store

A ação de opção mais comum é store, que diz ao optparse para pegar o próximo argumento (ou o restante do argumento atual), garantir que seja do tipo correto e armazená-lo no destino escolhido.

Por exemplo:

parser.add_option("-f", "--file",
                  action="store", type="string", dest="filename")

Agora vamos criar uma linha de comando falsa e pedir ao optparse para analisá-la:

args = ["-f", "foo.txt"]
(options, args) = parser.parse_args(args)

Quando optparse vê a string de opção -f, ele consome o próximo argumento, foo.txt, e o armazena em options.filename. Então, após essa chamada para parse_args(), options.filename é "foo.txt".

Alguns outros tipos de opção suportados por optparse são int e float. Aqui está uma opção que espera um argumento inteiro:

parser.add_option("-n", type="int", dest="num")

Note que esta opção não tem uma string de opção longa, o que é perfeitamente aceitável. Além disso, não há nenhuma ação explícita, já que o padrão é store.

Vamos analisar outra linha de comando falsa. Desta vez, vamos colocar o argumento de opção bem perto da opção: já que -n42 (um argumento) equivale a -n 42 (dois argumentos), o código

(options, args) = parser.parse_args(["-n42"])
print(options.num)

vai exibir 42.

Se você não especificar um tipo, optparse presume string. Combinado com o fato de que a ação padrão é store, isso significa que nosso primeiro exemplo pode ser muito mais curto:

parser.add_option("-f", "--file", dest="filename")

Se você não fornecer um destino, optparse descobre um padrão sensato a partir das strings de opção: se a primeira string de opção longa for --foo-bar, então o destino padrão é foo_bar. Se não houver strings de opção longas, optparse olha para a primeira string de opção curta: o destino padrão para -f é f.

optparse também inclui o tipo complex embutido. Adicionar tipos é abordado na seção Estendendo optparse.

Manipulando opções (sinalizadores) booleanas

Opções de sinalizador — define uma variável como true ou false quando uma opção específica é vista — são bem comuns. optparse suporta-as com duas ações separadas, store_true e store_false. Por exemplo, você pode ter um sinalizador verbose que é ativado com -v e desativado com -q:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose")

Aqui temos duas opções diferentes com o mesmo destino, o que é perfeitamente OK. (Isso significa apenas que você tem que ter um pouco de cuidado ao definir valores padrão — veja abaixo.)

Quando optparse encontra -v na linha de comando, ele define options.verbose como True; quando encontra -q, options.verbose é definido como False.

Outras ações

Algumas outras ações suportadas por optparse são:

"store_const"

armazena um valor constante, predefinido via Option.const

"append"

anexa o argumento desta opção a uma lista

"count"

incrementa um contador em um

"callback"

chama uma função especificada

Elas são abordadas na seção Guia de referência e na seção Funções de retorno de opção.

Valores padrão

Todos os exemplos acima envolvem a configuração de alguma variável (o “destino”) quando certas opções de linha de comando são vistas. O que acontece se essas opções nunca forem vistas? Como não fornecemos nenhum padrão, todas elas são definidas como None. Isso geralmente é bom, mas às vezes você quer mais controle. optparse permite que você forneça um valor padrão para cada destino, que é atribuído antes da análise da linha de comando.

Primeiro, considere o exemplo de verbose/quiet. Se quisermos que optparse defina verbose como True a menos que -q seja visto, então podemos fazer isso:

parser.add_option("-v", action="store_true", dest="verbose", default=True)
parser.add_option("-q", action="store_false", dest="verbose")

Como os valores padrão se aplicam ao destino e não a qualquer opção específica, e essas duas opções têm o mesmo destino, isso é exatamente equivalente:

parser.add_option("-v", action="store_true", dest="verbose")
parser.add_option("-q", action="store_false", dest="verbose", default=True)

Considere isso:

parser.add_option("-v", action="store_true", dest="verbose", default=False)
parser.add_option("-q", action="store_false", dest="verbose", default=True)

Novamente, o valor padrão para verbose será True: o último valor padrão fornecido para qualquer destino específico é o que conta.

Uma maneira mais clara de especificar valores padrão é o método set_defaults() do OptionParser, que você pode chamar a qualquer momento antes de chamar parse_args():

parser.set_defaults(verbose=True)
parser.add_option(...)
(options, args) = parser.parse_args()

Como antes, o último valor especificado para um destino de opção dado é o que conta. Para maior clareza, tente usar um método ou outro de configuração de valores padrão, não ambos.

Gerando texto de ajuda

A capacidade do optparse de gerar texto de ajuda e uso automaticamente é útil para criar interfaces de linha de comando amigáveis ​​ao usuário. Tudo o que você precisa fazer é fornecer um valor help para cada opção e, opcionalmente, uma curta mensagem de uso para todo o seu programa. Aqui está um OptionParser preenchido com opções amigáveis (documentadas) ​​ao usuário:

usage = "usage: %prog [options] arg1 arg2"
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose",
                  action="store_true", dest="verbose", default=True,
                  help="make lots of noise [default]")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose",
                  help="be vewwy quiet (I'm hunting wabbits)")
parser.add_option("-f", "--filename",
                  metavar="FILE", help="write output to FILE")
parser.add_option("-m", "--mode",
                  default="intermediate",
                  help="interaction mode: novice, intermediate, "
                       "or expert [default: %default]")

Se optparse encontrar -h ou --help na linha de comando, ou se você apenas chamar parser.print_help(), ele exibe o seguinte na saída padrão:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or
                        expert [default: intermediate]

(Se a saída de ajuda for acionada por uma opção de ajuda, optparse sai após imprimir o texto de ajuda.)

Há muita coisa acontecendo aqui para ajudar optparse a gerar a melhor mensagem de ajuda possível:

  • o script define sua própria mensagem de uso:

    usage = "usage: %prog [options] arg1 arg2"
    

    optparse expande %prog na string de uso para o nome do programa atual, ou seja, os.path.basename(sys.argv[0]). A string expandida é então exibida antes da ajuda detalhada da opção.

    Se você não fornecer uma string de uso, optparse usa um padrão simples, mas sensato: "Usage: %prog [options]", o que é bom se seu script não aceita nenhum argumento posicional.

  • cada opção define uma string de ajuda e não se preocupa com quebra de linha — optparse cuida da quebra de linhas e faz com que a saída de ajuda tenha uma boa aparência.

  • opções que assumem um valor indicam esse fato em sua mensagem de ajuda gerada automaticamente, por exemplo, para a opção “mode”:

    -m MODE, --mode=MODE
    

    Aqui, “MODE” é chamado de metavariável: ele representa o argumento que o usuário deve fornecer para -m/--mode. Por padrão, optparse converte o nome da variável de destino para maiúsculas e usa isso para a metavariável. Às vezes, não é isso que você quer — por exemplo, a opção --filename define explicitamente metavar="FILE", resultando nesta descrição de opção gerada automaticamente:

    -f FILE, --filename=FILE
    

    Isso é importante para mais do que apenas economizar espaço: o texto de ajuda escrito manualmente usa a metavariável FILE para dar uma pista ao usuário de que há uma conexão entre a sintaxe semiformal -f FILE e a descrição semântica informal como, por exemplo, “write output to FILE”. Essa é uma maneira simples, mas eficaz, de tornar seu texto de ajuda muito mais claro e útil para usuários finais.

  • opções que têm um valor padrão podem incluir %default na string de ajuda — optparse vai substituí-lo por str() do valor padrão da opção. Se uma opção não tiver um valor padrão (ou o valor padrão for None), %default expande para none.

Agrupando opções

Ao lidar com muitas opções, é conveniente agrupar essas opções para melhor saída de ajuda. Um OptionParser pode conter vários grupos de opções, cada um dos quais pode conter várias opções.

Um grupo de opções é obtido usando a classe OptionGroup:

class optparse.OptionGroup(parser, title, description=None)

onde

  • parser é a instância OptionParser na qual o grupo será inserido

  • title é o título do grupo

  • description, opcional, é uma descrição longa do grupo

OptionGroup herda de OptionContainer (como OptionParser) e, portanto, o método add_option() pode ser usado para adicionar uma opção ao grupo.

Depois que todas as opções são declaradas, usando o método OptionParser add_option_group() o grupo é adicionado ao analisador definido anteriormente.

Continuando com o analisador definido na seção anterior, adicionar um OptionGroup a um analisador é fácil:

group = OptionGroup(parser, "Dangerous Options",
                    "Caution: use these options at your own risk.  "
                    "It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)

Isso resultaria na seguinte saída de texto de ajuda:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or
                        expert [default: intermediate]

  Dangerous Options:
    Caution: use these options at your own risk.  It is believed that some
    of them bite.

    -g                  Group option.

Um exemplo um pouco mais completo pode envolver o uso de mais de um grupo: ainda estendendo o exemplo anterior:

group = OptionGroup(parser, "Dangerous Options",
                    "Caution: use these options at your own risk.  "
                    "It is believed that some of them bite.")
group.add_option("-g", action="store_true", help="Group option.")
parser.add_option_group(group)

group = OptionGroup(parser, "Debug Options")
group.add_option("-d", "--debug", action="store_true",
                 help="Print debug information")
group.add_option("-s", "--sql", action="store_true",
                 help="Print all SQL statements executed")
group.add_option("-e", action="store_true", help="Print every action done")
parser.add_option_group(group)

que resulta na seguinte saída:

Usage: <yourscript> [options] arg1 arg2

Options:
  -h, --help            show this help message and exit
  -v, --verbose         make lots of noise [default]
  -q, --quiet           be vewwy quiet (I'm hunting wabbits)
  -f FILE, --filename=FILE
                        write output to FILE
  -m MODE, --mode=MODE  interaction mode: novice, intermediate, or expert
                        [default: intermediate]

  Dangerous Options:
    Caution: use these options at your own risk.  It is believed that some
    of them bite.

    -g                  Group option.

  Debug Options:
    -d, --debug         Print debug information
    -s, --sql           Print all SQL statements executed
    -e                  Print every action done

Outro método interessante, especialmente ao trabalhar programaticamente com grupos de opções, é:

OptionParser.get_option_group(opt_str)

Retorna o objeto OptionGroup ao qual a string de opção curta ou longa opt_str (por exemplo, '-o' ou '--option') pertence. Se não houver tal OptionGroup, retorna None.

Exibindo uma string de versão

Similar à string breve de uso, optparse também pode exibir uma string de versão para seu programa. Você tem que fornecer a string como o argumento version para OptionParser:

parser = OptionParser(usage="%prog [-f] [-q]", version="%prog 1.0")

%prog é expandido assim como em usage. Além disso, version pode conter qualquer coisa que você quiser. Quando você o fornece, optparse adiciona automaticamente uma opção --version ao seu analisador. Se ele encontrar essa opção na linha de comando, ele expande sua string version (substituindo %prog), exibindo-a no stdout e sai.

Por exemplo, se o seu script for chamado /usr/bin/foo:

$ /usr/bin/foo --version
foo 1.0

Os dois métodos a seguir podem ser usados ​​para exibir e obter a string version:

OptionParser.print_version(file=None)

Exibe a mensagem de versão para o programa atual (self.version) em file (stdout padrão). Assim como em print_usage(), qualquer ocorrência de %prog em self.version é substituída pelo nome do programa atual. Não faz nada se self.version estiver vazio ou indefinido.

OptionParser.get_version()

O mesmo que print_version(), mas retorna a string da versão em vez de exibi-la.

Como optparse trata erros

Existem duas classes amplas de erros com os quais optparse precisa se preocupar: erros do programador e erros do usuário. Erros do programador geralmente são chamadas errôneas para OptionParser.add_option(), por exemplo, strings de opção inválidas, atributos de opção desconhecidos, atributos de opção ausentes, etc. Eles são tratados da maneira usual: levanta uma exceção (seja optparse.OptionError ou TypeError) e deixe o programa travar.

Lidar com erros do usuário é muito mais importante, pois eles certamente acontecerão não importa quão estável seu código seja. optparse pode detectar automaticamente alguns erros do usuário, como argumentos de opção ruins (passando -n 4x onde -n recebe um argumento inteiro), argumentos ausentes (-n no final da linha de comando, onde -n recebe um argumento de qualquer tipo). Além disso, você pode chamar OptionParser.error() para sinalizar uma condição de erro definida pelo aplicativo:

(options, args) = parser.parse_args()
...
if options.a and options.b:
    parser.error("options -a and -b are mutually exclusive")

Em ambos os casos, optparse lida com o erro da mesma maneira: ele imprime a mensagem de uso do programa e uma mensagem de erro no erro padrão e sai com o status de erro 2.

Considere o primeiro exemplo acima, onde o usuário passa 4x para uma opção que aceita um inteiro:

$ /usr/bin/foo -n 4x
Usage: foo [options]

foo: error: option -n: invalid integer value: '4x'

Ou, quando o usuário não passa nenhum valor:

$ /usr/bin/foo -n
Usage: foo [options]

foo: error: -n option requires an argument

As mensagens de erro geradas pelo optparse tomam o cuidado de sempre mencionar a opção envolvida no erro; certifique-se de fazer o mesmo ao chamar OptionParser.error() do código do sua aplicação.

Se o comportamento padrão de tratamento de erros do optparse não atender às suas necessidades, você precisará criar uma subclasse de OptionParser e substituir seus métodos exit() e/ou error().

Juntando tudo

Veja como os scripts baseados no optparse geralmente se parecem:

from optparse import OptionParser
...
def main():
    usage = "usage: %prog [options] arg"
    parser = OptionParser(usage)
    parser.add_option("-f", "--file", dest="filename",
                      help="read data from FILENAME")
    parser.add_option("-v", "--verbose",
                      action="store_true", dest="verbose")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose")
    ...
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error("incorrect number of arguments")
    if options.verbose:
        print("reading %s..." % options.filename)
    ...

if __name__ == "__main__":
    main()

Guia de referência

Criando o analisador sintático

O primeiro passo para usar o optparse é criar uma instância de OptionParser.

class optparse.OptionParser(...)

O construtor do OptionParser não tem argumentos obrigatórios, mas vários argumentos nomeados opcionais. Você deve sempre passá-los como argumentos nomeados, ou seja, não confie na ordem em que os argumentos são declarados.

usage (padrão: "%prog [options]")

O resumo de uso para exibir quando seu programa é executado incorretamente ou com uma opção de ajuda. Quando optparse exibe a string de uso, ele expande %prog para os.path.basename(sys.argv[0]) (ou para prog se você passou esse argumento nomeado). Para suprimir uma mensagem de uso, passe o valor especial optparse.SUPPRESS_USAGE.

option_list (padrão: [])

Uma lista de objetos Option para preencher o analisador sintático. As opções em option_list são adicionadas após quaisquer opções em standard_option_list (um atributo de classe que pode ser definido por subclasses de OptionParser), mas antes de quaisquer opções de versão ou ajuda. Descontinuado; use add_option() após criar o analisador sintático.

option_class (padrão: optparse.Option)

Classe para usar ao adicionar opções ao analisador sintático em add_option().

version (padrão: None)

Uma string de versão para exibir quando o usuário fornece uma opção de versão. Se você fornecer um valor true para version, optparse adiciona automaticamente uma opção de versão com a string de opção única --version. A substring %prog é expandida da mesma forma que para usage.

conflict_handler (padrão: "error")

Especifica o que fazer quando opções com strings de opções conflitantes são adicionadas ao analisador sintático; consulte a seção Conflitos entre opções.

description (padrão: None)

Um parágrafo de texto que fornece uma breve visão geral do seu programa. optparse reformata este parágrafo para ajustá-lo à largura atual do terminal e o exibe quando o usuário solicita ajuda (depois de usage, mas antes da lista de opções).

formatter (padrão: um novo IndentedHelpFormatter)

Uma instância de optparse.HelpFormatter que será usada para exibir um texto de ajuda. optparse fornece duas classes concretas para essa finalidade: IndentedHelpFormatter e TitledHelpFormatter.

add_help_option (padrão: True)

Se verdadeiro, optparse adicionará uma opção de ajuda (com strings de opção -h e --help) ao analisador sintático.

prog

A string a ser usada ao expandir %prog em usage e version em vez de os.path.basename(sys.argv[0]).

epilog (padrão: None)

Um parágrafo de texto de ajuda para exibir após a ajuda da opção.

Preenchendo o analisador sintático

Há várias maneiras de preencher o analisador sintático com opções. A maneira preferida é usando OptionParser.add_option(), como mostrado na seção Tutorial. add_option() pode ser chamado de uma das duas maneiras:

  • passar uma instância de Option (conforme retornado por make_option())

  • passar qualquer combinação de argumentos nomeados e posicionais que sejam aceitáveis ​​para make_option() (ou seja, para o construtor de Option), e ela criará a instância de Option para você

A outra alternativa é passar uma lista de instâncias de Option pré-construídas para o construtor de OptionParser, como em:

option_list = [
    make_option("-f", "--filename",
                action="store", type="string", dest="filename"),
    make_option("-q", "--quiet",
                action="store_false", dest="verbose"),
    ]
parser = OptionParser(option_list=option_list)

(make_option() é uma função de fábrica para criar instâncias de Option; atualmente é um apelido para o construtor de Option. Uma versão futura de optparse pode dividir Option em várias classes, e make_option() escolherá a classe certa para instanciar. Não instancie Option diretamente.)

Definindo as opções

Cada instância de Option representa um conjunto de strings de opções de linha de comando sinônimas, por exemplo, -f e --file. Você pode especificar qualquer número de strings de opções curtas ou longas, mas deve especificar pelo menos uma string de opção geral.

A maneira canônica de criar uma instância de Option é com o método add_option() de OptionParser.

OptionParser.add_option(option)
OptionParser.add_option(*opt_str, attr=value, ...)

Para definir uma opção com apenas uma sequência de opções curta:

parser.add_option("-f", attr=value, ...)

E para definir uma opção com apenas uma longa sequência de opções:

parser.add_option("--foo", attr=value, ...)

Os argumentos nomeados definem atributos do novo objeto Option. O atributo option mais importante é action, e ele determina amplamente quais outros atributos são relevantes ou obrigatórios. Se você passar atributos option irrelevantes, ou deixar de passar os obrigatórios, optparse levanta uma exceção OptionError explicando seu erro.

A action de uma opção determina o que optparse faz quando encontra essa opção na linha de comando. As ações de opção padrão codificadas no optparse são:

"store"

armazena o argumento desta opção (padrão)

"store_const"

armazena um valor constante, predefinido via Option.const

"store_true"

armazena True

"store_false"

armazena False

"append"

anexa o argumento desta opção a uma lista

"append_const"

anexar um valor constante a uma lista, predefinido via Option.const

"count"

incrementa um contador em um

"callback"

chama uma função especificada

"help"

exibe uma mensagem de uso incluindo todas as opções e a documentação para elas

(Se você não fornecer uma ação, o padrão é "store". Para esta ação, você também pode fornecer os atributos de opção type e dest; consulte Ações de opção padrão.)

Como você pode ver, a maioria das ações envolve armazenar ou atualizar um valor em algum lugar. optparse sempre cria um objeto especial para isso, convencionalmente chamado de options, que é uma instância de optparse.Values.

class optparse.Values

Um objeto que contém nomes e valores de argumentos analisados ​​como atributos. Normalmente criado chamando ao chamar OptionParser.parse_args(), e pode ser substituído por uma subclasse personalizada passada para o argumento values de OptionParser.parse_args() (conforme descrito em Análise de argumentos).

Argumentos de opção (e vários outros valores) são armazenados como atributos deste objeto, de acordo com o atributo de opção dest (destino).

Por exemplo, quando você chama

parser.parse_args()

uma das primeiras coisas que optparse faz é criar o objeto options:

options = Values()

Se uma das opções neste analisador sintático for definida com

parser.add_option("-f", "--file", action="store", type="string", dest="filename")

e a linha de comando que está sendo analisada inclui qualquer um dos seguintes:

-ffoo
-f foo
--file=foo
--file foo

então optparse, ao ver esta opção, fará o equivalente a

options.filename = "foo"

Os atributos de opção type e dest são quase tão importantes quanto action, mas action é o único que faz sentido para todas as opções.

Atributos da classe Option

class optparse.Option

Um único argumento de linha de comando, com vários atributos passados ​​como nomeados para o construtor. Normalmente criado com OptionParser.add_option() em vez de diretamente, e pode ser substituído por uma classe personalizada por meio do argumento option_class para OptionParser.

Os seguintes atributos de opção podem ser passados ​​como argumentos nomeados para OptionParser.add_option(). Se você passar um atributo de opção que não seja relevante para uma opção específica, ou deixar de passar um atributo de opção obrigatório, optparse levanta OptionError.

Option.action

(padrão: "store")

Determina o comportamento de optparse quando esta opção é vista na linha de comando; as opções disponíveis estão documentadas aqui.

Option.type

(padrão: "string")

O tipo de argumento esperado por esta opção (por exemplo, "string" ou "int"); os tipos de opções disponíveis estão documentados aqui.

Option.dest

(padrão: derivado de strings de opção)

Se a ação da opção implicar escrever ou modificar um valor em algum lugar, isso informa ao optparse onde escrevê-lo: dest nomeia um atributo do objeto options que o optparse constrói ao analisar a linha de comando.

Option.default

O valor para usar para o destino desta opção se a opção não for vista na linha de comando. Veja também OptionParser.set_defaults().

Option.nargs

(padrão: 1)

Quantos argumentos do tipo type devem ser consumidos quando esta opção for vista. Se > 1, optparse armazenará uma tupla de valores em dest.

Option.const

Para ações que armazenam um valor constante, o valor constante a ser armazenado.

Option.choices

Para opções do tipo "choice", a lista de strings que o usuário pode escolher.

Option.callback

Para opções com ação "callback", o chamável para chamar quando esta opção for vista. Veja a seção Funções de retorno de opção para detalhes sobre os argumentos passados ​​para o chamável.

Option.callback_args
Option.callback_kwargs

Argumentos nomeados e posicionais adicionais para passar para callback após os quatro argumentos de retorno de chamada padrão.

Option.help

Texto de ajuda para exibir para esta opção ao listar todas as opções disponíveis após o usuário fornecer uma opção help (como --help). Se nenhum texto de ajuda for fornecido, a opção será listada sem texto de ajuda. Para ocultar esta opção, use o valor especial optparse.SUPPRESS_HELP.

Option.metavar

(padrão: derivado de strings de opção)

Substituto para o(s) argumento(s) de opção a ser(em) usado(s) ao exibir texto de ajuda. Veja a seção Tutorial para um exemplo.

Ações de opção padrão

As várias ações de opção têm requisitos e efeitos ligeiramente diferentes. A maioria das ações tem vários atributos de opção relevantes que você pode especificar para guiar o comportamento de optparse; algumas têm atributos obrigatórios, que você deve especificar para qualquer opção que use essa ação.

  • "store" [relevante: type, dest, nargs, choices]

    A opção deve ser seguida por um argumento, que é convertido em um valor de acordo com type e armazenado em dest. Se nargs > 1, vários argumentos serão consumidos da linha de comando; todos serão convertidos de acordo com type e armazenados em dest como uma tupla. Veja a seção Tipos de opção padrão.

    Se choices for fornecido (uma lista ou tupla de strings), o tipo padrão será "choice".

    Se type não for fornecido, o padrão será "string".

    Se dest não for fornecido, optparse deriva um destino da primeira string de opção longa (por exemplo, --foo-bar implica foo_bar). Se não houver strings de opção longas, optparse deriva um destino da primeira string de opção curta (por exemplo, -f implica f).

    Exemplo:

    parser.add_option("-f")
    parser.add_option("-p", type="float", nargs=3, dest="point")
    

    Como ele analisa a linha de comando

    -f foo.txt -p 1 -3.5 4 -fbar.txt
    

    optparse vai definir

    options.f = "foo.txt"
    options.point = (1.0, -3.5, 4.0)
    options.f = "bar.txt"
    
  • "store_const" [obrigatório: const; relevante: dest]

    O valor de const é armazenado em dest.

    Exemplo:

    parser.add_option("-q", "--quiet",
                      action="store_const", const=0, dest="verbose")
    parser.add_option("-v", "--verbose",
                      action="store_const", const=1, dest="verbose")
    parser.add_option("--noisy",
                      action="store_const", const=2, dest="verbose")
    

    Se --noisy é encontrado, optparse vai definir

    options.verbose = 2
    
  • "store_true" [relevante: dest]

    Um caso especial de "store_const" que armazena True em dest.

  • "store_false" [relevante: dest]

    Como "store_true", mas armazenad False.

    Exemplo:

    parser.add_option("--clobber", action="store_true", dest="clobber")
    parser.add_option("--no-clobber", action="store_false", dest="clobber")
    
  • "append" [relevante: type, dest, nargs, choices]

    A opção deve ser seguida por um argumento, que é anexado à lista em dest. Se nenhum valor padrão para dest for fornecido, uma lista vazia será criada automaticamente quando optparse encontrar esta opção pela primeira vez na linha de comando. Se nargs > 1, vários argumentos serão consumidos e uma tupla de comprimento nargs será anexada a dest.

    Os padrões para type e dest são os mesmos da ação "store".

    Exemplo:

    parser.add_option("-t", "--tracks", action="append", type="int")
    

    Se -t3 for encontrado na linha de comando, optparse faz o equivalente a:

    options.tracks = []
    options.tracks.append(int("3"))
    

    Se, um pouco mais tarde, --tracks=4 for encontrado, ele faz:

    options.tracks.append(int("4"))
    

    A ação append chama o método append no valor atual da opção. Isso significa que qualquer valor padrão especificado deve ter um método append. Isso também significa que se o valor padrão não for vazio, os elementos padrão estarão presentes no valor analisado para a opção, com quaisquer valores da linha de comando anexados após esses valores padrão:

    >>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults'])
    >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg'])
    >>> opts.files
    ['~/.mypkg/defaults', 'overrides.mypkg']
    
  • "append_const" [obrigatório: const; relevante: dest]

    Como "store_const", mas o valor de const é anexado a dest; assim como em "append", dest assume como padrão None, e uma lista vazia é criada automaticamente na primeira vez que a opção é encontrada.

  • "count" [relevante: dest]

    Incrementa o inteiro armazenado em dest. Se nenhum valor padrão for fornecido, dest é definido como zero antes de ser incrementado pela primeira vez.

    Exemplo:

    parser.add_option("-v", action="count", dest="verbosity")
    

    A primeira vez que -v é encontrado na linha de comando, optparse faz o equivalente a:

    options.verbosity = 0
    options.verbosity += 1
    

    Cada ocorrência subsequente de -v resulta em

    options.verbosity += 1
    
  • "callback" [obrigatório: callback; relevante: type, nargs, callback_args, callback_kwargs]

    Chama a função especificada por callback, que é chamada como

    func(option, opt_str, value, parser, *args, **kwargs)
    

    Veja a seção Funções de retorno de opção para mais detalhes.

  • "help"

    Exibe uma mensagem de ajuda completa para todas as opções no analisador sintático de opções atual. A mensagem de ajuda é construída a partir da string usage passada para o construtor do OptionParser e da string help passada para cada opção.

    Se nenhuma string de help for fornecida para uma opção, ela ainda será listada na mensagem de ajuda. Para omitir uma opção completamente, use o valor especial optparse.SUPPRESS_HELP.

    optparse adiciona automaticamente uma opção help a todos as instâncias de OptionParsers, então normalmente você não precisa criar uma.

    Exemplo:

    from optparse import OptionParser, SUPPRESS_HELP
    
    # geralmente, uma opção de ajuda é adicionada
    # automaticamente, mas que podem ser suprimida
    # usando o argumento add_help_option
    parser = OptionParser(add_help_option=False)
    
    parser.add_option("-h", "--help", action="help")
    parser.add_option("-v", action="store_true", dest="verbose",
                      help="Be moderately verbose")
    parser.add_option("--file", dest="filename",
                      help="Input file to read data from")
    parser.add_option("--secret", help=SUPPRESS_HELP)
    

    Se optparse encontrar -h ou --help na linha de comando, ele vai exibir algo como a seguinte mensagem de ajuda no stdout (presumindo que sys.argv[0] é "foo.py"):

    Usage: foo.py [options]
    
    Options:
      -h, --help        Show this help message and exit
      -v                Be moderately verbose
      --file=FILENAME   Input file to read data from
    

    Após exibir a mensagem de ajuda, optparse encerra seu processo com sys.exit(0).

  • "version"

    Exibe o número da versão fornecido à instância de OptionParser para stdout e sai. O número da versão é realmente formatado e exibido pelo método print_version() do OptionParser. Geralmente, é relevante somente se o argumento version for fornecido ao construtor de OptionParser. Assim como com as opções de help, você raramente criará opções version, já que optparse as adiciona automaticamente quando necessário.

Tipos de opção padrão

optparse tem cinco tipos de opções embutidos: "string", "int", "choice", "float" e "complex". Se você precisar adicionar novos tipos de opções, veja a seção Estendendo optparse.

Os argumentos para opções de string não são verificados ou convertidos de forma alguma: o texto na linha de comando é armazenado no destino (ou passado para a função de retorno) como está.

Argumentos inteiros (tipo "int") são analisados ​​da seguinte forma:

  • se o número começar com 0x, ele será analisado como um número hexadecimal

  • se o número começar com 0, ele será analisado como um número octal

  • se o número começar com 0b, ele será analisado como um número binário

  • caso contrário, o número é analisado como um número decimal

A conversão é feita chamando int() com a base apropriada (2, 8, 10 ou 16). Se isso falhar, optparse também falhará, embora com uma mensagem de erro mais útil.

Os argumentos de opção "float" e "complex" são convertidos diretamente com float() e complex(), com tratamento de erros semelhante.

As opções "choice" são um subtipo das opções "string". O atributo da opção choices (uma sequência de strings) define o conjunto de argumentos de opção permitidos. optparse.check_choice() compara os argumentos de opção fornecidos pelo usuário com esta lista mestre e levanta OptionValueError se uma string inválida for fornecida.

Análise de argumentos

O objetivo de criar e preencher uma instância de OptionParser é chamar seu método parse_args().

OptionParser.parse_args(args=None, values=None)

Analisa as opções de linha de comando encontradas em args.

Os parâmetros de entrada são

args

a lista de argumentos para processar (padrão: sys.argv[1:])

values

um objeto Values para armazenar argumentos de opção (padrão: uma nova instância de Values) – se você fornecer um objeto existente, os padrões de opção não serão inicializados nele

e o valor de retorno é um par (options, args) sendo

options

o mesmo objeto que foi passado como values, ou a instância optparse.Values criada por optparse

args

os argumentos posicionais restantes depois que todas as opções foram processadas

O uso mais comum é não fornecer nenhum argumento nomeado. Se você fornecer values, ele será modificado com chamadas repetidas de setattr() (aproximadamente uma para cada argumento de opção armazenado em um destino de opção) e retornado por parse_args().

Se parse_args() encontrar algum erro na lista de argumentos, ele chama o método error() da instância de OptionParser com uma mensagem de erro apropriada para o usuário final. Isso, em última análise, encerra seu processo com um status de saída 2 (o status de saída tradicional do Unix para erros de linha de comando).

Consultando e manipulando seu analisador sintático de opções

O comportamento padrão do analisador sintático de opções pode ser ligeiramente personalizado, e você também pode dar uma olhada no seu analisador de opções e ver o que há lá. A classe OptionParser fornece vários métodos para ajudar você:

OptionParser.disable_interspersed_args()

Define a análise para parar na primeira não opção. Por exemplo, se -a e -b forem ambas opções simples que não aceitam argumentos, optparse normalmente aceita esta sintaxe:

prog -a arg1 -b arg2

e trata-a como equivalente a

prog -a -b arg1 arg2

Para desabilitar esse recurso, chame disable_interspersed_args(). Isso restaura a sintaxe Unix tradicional, onde a análise de opções para com o primeiro argumento não-opcional.

Use isto se você tiver um processador de comando que executa outro comando que tem opções próprias e você quer ter certeza de que essas opções não fiquem confusas. Por exemplo, cada comando pode ter um conjunto diferente de opções.

OptionParser.enable_interspersed_args()

Define a análise para não parar na primeira não opção, permitindo intercalar alternadores com argumentos de comando. Esse é o comportamento padrão.

OptionParser.get_option(opt_str)

Retorna a instância de Option com a string de opção opt_str, ou None se nenhuma opção tiver essa string de opção.

OptionParser.has_option(opt_str)

Retorna True se o objeto OptionParser tiver uma opção com string de opção opt_str (por exemplo, -q ou --verbose).

OptionParser.remove_option(opt_str)

Se o OptionParser tiver uma opção correspondente a opt_str, essa opção será removida. Se essa opção fornecer quaisquer outras strings de opção, todas essas strings de opção se tornarão inválidas. Se opt_str não ocorrer em nenhuma opção pertencente a este OptionParser, levanta ValueError.

Conflitos entre opções

Se você não tomar cuidado, é fácil definir opções com strings de opções conflitantes:

parser.add_option("-n", "--dry-run", ...)
...
parser.add_option("-n", "--noisy", ...)

(Isto é particularmente verdadeiro se você definiu sua própria subclasse de OptionParser com algumas opções padrão.)

Toda vez que você adiciona uma opção, optparse verifica se há conflitos com opções existentes. Se encontrar algum, ele invoca o mecanismo de tratamento de conflitos atual. Você pode definir o mecanismo de tratamento de conflitos no construtor:

parser = OptionParser(..., conflict_handler=handler)

ou com uma chamada separada:

parser.set_conflict_handler(handler)

Os manipuladores de conflitos disponíveis são:

"error" (padrão)

presume que os conflitos de opções são um erro de programação e levanta OptionConflictError

"resolve"

resolve conflitos de opções de forma inteligente (veja abaixo)

Como exemplo, vamos definir um OptionParser que resolve conflitos de forma inteligente e adiciona opções conflitantes a ele:

parser = OptionParser(conflict_handler="resolve")
parser.add_option("-n", "--dry-run", ..., help="do no harm")
parser.add_option("-n", "--noisy", ..., help="be noisy")

Neste ponto, optparse detecta que uma opção adicionada anteriormente já está usando a string de opção -n. Como conflict_handler é "resolve", ele resolve a situação removendo -n da lista de strings de opção da opção anterior. Agora --dry-run é a única maneira do usuário ativar essa opção. Se o usuário pedir ajuda, a mensagem de ajuda refletirá isso:

Options:
  --dry-run     do no harm
  ...
  -n, --noisy   be noisy

É possível reduzir as strings de opção para uma opção adicionada anteriormente até que não haja mais nenhuma, e o usuário não tenha como invocar essa opção da linha de comando. Nesse caso, optparse remove essa opção completamente, então ela não aparece no texto de ajuda ou em nenhum outro lugar. Continuando com nosso objeto OptionParser existente:

parser.add_option("--dry-run", ..., help="new dry-run option")

Neste ponto, a opção original -n/--dry-run não está mais acessível, então optparse a remove, deixando este texto de ajuda:

Options:
  ...
  -n, --noisy   be noisy
  --dry-run     new dry-run option

Limpeza

As instâncias de OptionParser têm várias referências cíclicas. Isso não deve ser um problema para o coletor de lixo do Python, mas você pode desejar quebrar as referências cíclicas explicitamente chamando destroy() no seu OptionParser quando terminar de usá-lo. Isso é particularmente útil em aplicações de longa execução, onde gráficos de objetos grandes podem ser acessados ​​do seu OptionParser.

Outros métodos

OptionParser provê vários outros métodos públicos:

OptionParser.set_usage(usage)

Defina a string de uso de acordo com as regras descritas acima para o argumento nomeado do construtor usage. Passar None define a string de uso padrão; use optparse.SUPPRESS_USAGE para suprimir uma mensagem de uso.

OptionParser.print_usage(file=None)

Exibe a mensagem de uso para o programa atual (self.usage) em file (stdout padrão). Qualquer ocorrência da string %prog em self.usage é substituída pelo nome do programa atual. Não faz nada se self.usage estiver vazio ou não definido.

OptionParser.get_usage()

O mesmo que print_usage(), mas retorna a string de uso em vez de exibi-la.

OptionParser.set_defaults(dest=value, ...)

Define valores padrão para vários destinos de opção de uma vez. Usar set_defaults() é a maneira preferida de definir valores padrão para opções, já que várias opções podem compartilhar o mesmo destino. Por exemplo, se várias opções de “modo” definirem o mesmo destino, qualquer uma delas pode definir o padrão, e a última vence:

parser.add_option("--advanced", action="store_const",
                  dest="mode", const="advanced",
                  default="novice")    # substituída abaixo
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice",
                  default="advanced")  # substitui a configuração acima

Para evitar essa confusão, use set_defaults():

parser.set_defaults(mode="advanced")
parser.add_option("--advanced", action="store_const",
                  dest="mode", const="advanced")
parser.add_option("--novice", action="store_const",
                  dest="mode", const="novice")

Funções de retorno de opção

Quando as ações e tipos embutidos de optparse não são o bastante para suas necessidades, você tem duas escolhas: estender optparse ou definir uma opção de retorno de chamada. Estender optparse é mais geral, mas exagero para muitos casos simples. Muitas vezes, um retorno de chamada simples é tudo o que você precisa.

Há duas etapas para definir uma opção de retorno de chamada:

  • definir a opção em si usando a ação "callback"

  • escrever o função de retorno; esta é uma função (ou método) que recebe pelo menos quatro argumentos, conforme descrito abaixo

Definindo uma opção de retorno de chamada

Como sempre, a maneira mais fácil de definir uma opção de retorno de chamada é usando o método OptionParser.add_option(). Além de action, o único atributo de opção que você deve especificar é callback, a função a ser chamada:

parser.add_option("-c", action="callback", callback=my_callback)

callback é uma função (ou outro objeto chamável), então você já deve ter definido my_callback() quando criar esta opção de retorno de chamada. Neste caso simples, optparse nem sabe se -c aceita argumentos, o que geralmente significa que a opção não aceita argumentos — a mera presença de -c na linha de comando é tudo o que ela precisa saber. Em algumas circunstâncias, no entanto, você pode querer que seu retorno de chamada consuma um número arbitrário de argumentos de linha de comando. É aqui que escrever retornos de chamada fica complicado; isso é abordado mais adiante nesta seção.

optparse sempre passa quatro argumentos particulares para seu retorno de chamada, e ele só passará argumentos adicionais se você especificá-los via callback_args e callback_kwargs. Assim, a assinatura mínima da função de retorno de chamada é:

def my_callback(option, opt, value, parser):

Os quatro argumentos para um retorno de chamada são descritos abaixo.

Há vários outros atributos de opção que você pode fornecer ao definir uma opção de retorno de chamada:

type

tem seu significado usual: como com as ações "store" ou "append", ele instrui optparse a consumir um argumento e convertê-lo para type. Em vez de armazenar o(s) valor(es) convertido(s) em qualquer lugar, no entanto, optparse os passa para sua função de retorno de chamada.

nargs

também tem seu significado usual: se for fornecido e > 1, optparse consumirá argumentos nargs, cada um dos quais deve ser conversível para type. Em seguida, ele passa uma tupla de valores convertidos para seu retorno de chamada.

callback_args

uma tupla de argumentos posicionais extras para passar para a função de retorno

callback_kwargs

um dicionário de argumentos nomeados extras para passar para a função de retorno

Como os retornos de chamada são chamados

Todos os retornos de chamada são chamados da seguinte forma:

func(option, opt_str, value, parser, *args, **kwargs)

onde

option

é a instância de Option que está chamando o retorno de chamada

opt_str

é a string de opção vista na linha de comando que está acionando o retorno de chamada. (Se uma opção longa abreviada foi usada, opt_str será a string de opção canônica completa — por exemplo, se o usuário colocar --foo na linha de comando como uma abreviação para --foobar, então opt_str será "--foobar".)

value

é o argumento para esta opção visto na linha de comando. optparse só esperará um argumento se type estiver definido; o tipo de value será o tipo implícito pelo tipo da opção. Se type para esta opção for None (nenhum argumento esperado), então value será None. Se nargs > 1, value será uma tupla de valores do tipo apropriado.

parser

é a instância OptionParser que controla tudo, útil principalmente porque você pode acessar alguns outros dados interessantes por meio de seus atributos de instância:

parser.largs

a lista atual de argumentos restantes, ou seja, argumentos que foram consumidos, mas não são opções nem argumentos de opção. Sinta-se à vontade para modificar parser.largs, por exemplo, adicionando mais argumentos a ele. (Esta lista se tornará args, o segundo valor de retorno de parse_args().)

parser.rargs

a lista atual de argumentos restantes, ou seja, com opt_str e value (se aplicável) removidos, e apenas os argumentos que os seguem ainda lá. Sinta-se à vontade para modificar parser.rargs, por exemplo, consumindo mais argumentos.

parser.values

o objeto onde os valores de opção são armazenados por padrão (uma instância de optparse.OptionValues). Isso permite que as função de retorno usem o mesmo mecanismo que o resto de optparse para armazenar valores de opção; você não precisa mexer com globais ou closures. Você também pode acessar ou modificar o(s) valor(es) de quaisquer opções já encontradas na linha de comando.

args

é uma tupla de argumentos posicionais arbitrários fornecidos por meio do atributo de opção callback_args.

kwargs

é um dicionário de argumentos nomeados arbitrários fornecidos via callback_kwargs.

Levantando erros em uma função de retorno

A função de retorno de chamada deve levantar OptionValueError se houver algum problema com a opção ou seu(s) argumento(s). optparse captura isso e encerra o programa, exibindo a mensagem de erro que você fornece para stderr. Sua mensagem deve ser clara, concisa, precisa e mencionar a opção com defeito. Caso contrário, o usuário terá dificuldade em descobrir o que fez de errado.

Exemplo de função de retorno 1: retorno de chamada trivial

Aqui está um exemplo de uma opção de retorno de chamada que não aceita argumentos e simplesmente registra que a opção foi vista:

def record_foo_seen(option, opt_str, value, parser):
    parser.values.saw_foo = True

parser.add_option("--foo", action="callback", callback=record_foo_seen)

Claro, você pode fazer isso com a ação "store_true".

Exemplo de função de retorno 2: verificar a ordem das opções

Aqui está um exemplo um pouco mais interessante: registra o fato de que -a é visto, mas explode se ele vier depois de -b na linha de comando.

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use -a after -b")
    parser.values.a = 1
...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")

Exemplo 3 de função de retorno: verificar a ordem das opções (generalizada)

Se você quiser reutilizar essa função de retorno para várias opções semelhantes (definir um sinalizador, mas explodir se -b já tiver sido visto), será preciso um pouco de trabalho: a mensagem de erro e o sinalizador que ele define devem ser generalizados.

def check_order(option, opt_str, value, parser):
    if parser.values.b:
        raise OptionValueError("can't use %s after -b" % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')

Exemplo de função de retorno 4: verificar uma condição arbitrária

Claro, você pode colocar qualquer condição ali—você não está limitado a verificar os valores de opções já definidas. Por exemplo, se você tem opções que não devem ser chamadas quando a lua está cheia, tudo o que você tem a fazer é isto:

def check_moon(option, opt_str, value, parser):
    if is_moon_full():
        raise OptionValueError("%s option invalid when moon is full"
                               % opt_str)
    setattr(parser.values, option.dest, 1)
...
parser.add_option("--foo",
                  action="callback", callback=check_moon, dest="foo")

(A definição de is_moon_full() é deixada como um exercício para o leitor.)

Exemplo de função de retorno 5: argumentos fixos

As coisas ficam um pouco mais interessantes quando você define opções de retorno de chamada que aceitam um número fixo de argumentos. Especificar que uma opção de retorno de chamada aceita argumentos é semelhante a definir uma opção "store" ou "append": se você definir type, então a opção aceita um argumento que deve ser conversível para esse tipo; se você definir ainda nargs, então a opção aceita argumentos nargs.

Aqui está um exemplo que apenas emula a ação padrão "store":

def store_value(option, opt_str, value, parser):
    setattr(parser.values, option.dest, value)
...
parser.add_option("--foo",
                  action="callback", callback=store_value,
                  type="int", nargs=3, dest="foo")

Note que optparse cuida de consumir 3 argumentos e convertê-los em números inteiros para você; tudo o que você precisa fazer é armazená-los. (Ou o que for; obviamente você não precisa de uma função de retorno de chamada para este exemplo.)

Exemplo de função de retorno 6: argumentos variáveis

As coisas ficam complicadas quando você quer que uma opção receba um número variável de argumentos. Para esse caso, você deve escrever uma função de retorno, pois optparse não fornece nenhuma capacidade embutida para ele. E você tem que lidar com certas complexidades da análise sintática de linha de comando Unix convencional que optparse normalmente lida para você. Em particular, as funções de retorno devem implementar as regras convencionais para argumentos -- e - simples:

  • -- ou - podem ser argumentos de opção

  • -- apenas (se não for o argumento para alguma opção): interrompe o processamento da linha de comando e descarta o --

  • - apenas (se não for o argumento para alguma opção): interrompe o processamento da linha de comando, mas mantém o - (anexa-o a parser.largs)

Se você quiser uma opção que aceite um número variável de argumentos, há várias questões sutis e complicadas com as quais se preocupar. A implementação exata que você escolher será baseada em quais compensações você está disposto a fazer para sua aplicação (é por isso que optparse não oferece suporte a esse tipo de coisa diretamente).

No entanto, aqui vai uma tentativa de função de retorno para uma opção com argumentos variáveis:

def vararg_callback(option, opt_str, value, parser):
    assert value is None
    value = []

    def floatable(str):
        try:
            float(str)
            return True
        except ValueError:
            return False

    for arg in parser.rargs:
        # para em --foo como opções
        if arg[:2] == "--" and len(arg) > 2:
            break
        # para em -a, mas não em -3 ou -3.0
        if arg[:1] == "-" and len(arg) > 1 and not floatable(arg):
            break
        value.append(arg)

    del parser.rargs[:len(value)]
    setattr(parser.values, option.dest, value)

...
parser.add_option("-c", "--callback", dest="vararg_attr",
                  action="callback", callback=vararg_callback)

Estendendo optparse

Como os dois principais fatores de controle sobre como optparse interpreta as opções de linha de comando são a ação e o tipo de cada opção, a direção mais provável de extensão é adicionar novas ações e novos tipos.

Adicionando novos tipos

Para adicionar novos tipos, você precisa definir sua própria subclasse da classe Option de optparse. Esta classe tem alguns atributos que definem os tipos de optparse: TYPES e TYPE_CHECKER.

Option.TYPES

Uma tupla de nomes de tipos; na sua subclasse, basta definir uma nova tupla TYPES que se baseia na tupla padrão.

Option.TYPE_CHECKER

Um dicionário que mapeia nomes de tipos para funções de verificação de tipos. Uma função de verificação de tipos tem a seguinte assinatura:

def check_mytype(option, opt, value)

sendo option uma instância Option, opt é uma string de opção (por exemplo, -f), e value é a string da linha de comando que deve ser verificada e convertida para o tipo desejado. check_mytype() deve retornar um objeto do tipo hipotético mytype. O valor retornado por uma função de verificação de tipo acabará na instância OptionValues ​​retornada por OptionParser.parse_args(), ou será passado para uma função de retorno como o parâmetro value.

Sua função de verificação de tipo deve levantar OptionValueError se encontrar algum problema. OptionValueError recebe um único argumento de string, que é passado como está para o método error() do OptionParser, que por sua vez adiciona o nome do programa e a string "error:" e exibe tudo no stderr antes de encerrar o processo.

Aqui está um exemplo bobo que demonstra a adição de um tipo de opção "complex" para analisar números complexos no estilo Python na linha de comando. (Isso é ainda mais bobo do que costumava ser, porque optparse 1.3 adicionou suporte embutido para números complexos, mas não importa.)

Primeiro, as importações necessárias:

from copy import copy
from optparse import Option, OptionValueError

Você precisa definir seu verificador de tipo primeiro, pois ele será referenciado mais tarde (no atributo de classe TYPE_CHECKER da sua subclasse de Option):

def check_complex(option, opt, value):
    try:
        return complex(value)
    except ValueError:
        raise OptionValueError(
            "option %s: invalid complex value: %r" % (opt, value))

Finalmente, a subclasse de Option:

class MyOption (Option):
    TYPES = Option.TYPES + ("complex",)
    TYPE_CHECKER = copy(Option.TYPE_CHECKER)
    TYPE_CHECKER["complex"] = check_complex

(Se não fizéssemos uma copy() de Option.TYPE_CHECKER, acabaríamos modificando o atributo TYPE_CHECKER da classe Option de optparse. Sendo Python, nada impede você de fazer isso, exceto boas maneiras e bom senso.)

Pronto! Agora você pode escrever um script que usa o novo tipo de opção como qualquer outro script baseado em optparse, exceto que você tem que instruir seu OptionParser a usar MyOption em vez de Option:

parser = OptionParser(option_class=MyOption)
parser.add_option("-c", type="complex")

Como alternativa, você pode criar sua própria lista de opções e passá-la para o OptionParser; se você não usar add_option() da maneira acima, não precisa informar ao OptionParser qual classe de opção usar:

option_list = [MyOption("-c", action="store", type="complex", dest="c")]
parser = OptionParser(option_list=option_list)

Adicionando novas ações

A adição de novas ações é um pouco mais complicado, porque você precisa entender que optparse tem algumas classificações para ações:

Ações “store”

ações que resultam em optparse armazenando um valor em um atributo da instância OptionValues ​​atual; essas opções exigem que um atributo dest seja fornecido ao construtor Option.

Ações “typed”

Ações que pegam um valor da linha de comando e esperam que ele seja de um certo tipo; ou melhor, uma string que pode ser convertida para um certo tipo. Essas opções requerem um atributo type para o construtor Option.

Esses são conjuntos sobrepostos: algumas ações “store” padrão são "store", "store_const", "append" e "count", enquanto as ações “typed” padrão são "store", "append" e "callback".

Ao adicionar uma ação, você precisa categorizá-la listando-a em pelo menos um dos seguintes atributos de classe de Option (todos são listas de strings):

Option.ACTIONS

Todas as ações devem ser listadas em ACTIONS.

Option.STORE_ACTIONS

As ações “store” também são listadas aqui.

Option.TYPED_ACTIONS

As ações “typed” também são listadas aqui.

Option.ALWAYS_TYPED_ACTIONS

Ações que sempre assumem um tipo (ou seja, cujas opções sempre assumem um valor) são listadas aqui adicionalmente. O único efeito disso é que optparse atribui o tipo padrão, "string", a opções sem tipo explícito cuja ação é listada em ALWAYS_TYPED_ACTIONS.

Para realmente implementar sua nova ação, você deve substituir o método take_action() de Option e adicionar um caso que reconheça sua ação.

Por exemplo, vamos adicionar uma ação "extend". Isso é semelhante à ação padrão "append", mas em vez de pegar um único valor da linha de comando e anexá-lo a uma lista existente, "extend" pegará vários valores em uma única string delimitada por vírgulas e estenderá uma lista existente com eles. Ou seja, se --names for uma opção "extend" do tipo "string", a linha de comando

--names=foo,bar --names blah --names ding,dong

resultaria em uma lista

["foo", "bar", "blah", "ding", "dong"]

Novamente, nós definimos uma subclasse de Option:

class MyOption(Option):

    ACTIONS = Option.ACTIONS + ("extend",)
    STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
    TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
    ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)

    def take_action(self, action, dest, opt, value, values, parser):
        if action == "extend":
            lvalue = value.split(",")
            values.ensure_value(dest, []).extend(lvalue)
        else:
            Option.take_action(
                self, action, dest, opt, value, values, parser)

Características de nota:

  • "extend" espera um valor na linha de comando e armazena esse valor em algum lugar, então ele vai em STORE_ACTIONS e TYPED_ACTIONS.

  • para garantir que optparse atribua o tipo padrão de "string" às ações "extend", colocamos a ação "extend" em ALWAYS_TYPED_ACTIONS também.

  • MyOption.take_action() implementa apenas esta nova ação e passa o controle de volta para Option.take_action() para as ações padrão optparse.

  • values é uma instância da classe optparse_parser.Values, que fornece o método muito útil ensure_value(). ensure_value() é essencialmente getattr() com uma válvula de segurança; é chamado como

    values.ensure_value(attr, value)
    

    Se o atributo attr de values não existir ou for None, então ensure_value() primeiro o define como value e então retorna value. Isso é muito útil para ações como "extend", "append" e "count", todas as quais acumulam dados em uma variável e esperam que essa variável seja de um certo tipo (uma lista para as duas primeiras, um inteiro para a última). Usar ensure_value() significa que os scripts que usam sua ação não precisam se preocupar em definir um valor padrão para os destinos de opção em questão; eles podem simplesmente deixar o padrão como None e ensure_value() cuidará de acertar quando for necessário.

Exceções

exception optparse.OptionError

Levantada se uma instância de Option for criada com argumentos inválidos ou inconsistentes.

exception optparse.OptionConflictError

Levantada se opções conflitantes forem adicionadas a um instância de OptionParser.

exception optparse.OptionValueError

Levantada se um valor de opção inválido for encontrado na linha de comando.

exception optparse.BadOptionError

Levantada se uma opção inválida for passada na linha de comando.

exception optparse.AmbiguousOptionError

Levantada se uma opção ambígua for passada na linha de comando.