• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

rolando2424

[Python] [PyTeam] Como passar argumentos através da linha de comandos aos programas

4 mensagens neste tópico

NOTA: Se calhar este tutorial é mais virado para pessoas que usam Linux, devido ao facto de este tutorial ser sobre a linha de comandos, e o pessoal do Windows raramente usa o "cmd" (que também é uma treta, usem mas é o cygwin :D ). De qualquer modo, este tutorial também é aplicável às pessoas que querem escrever programas que corram da linha de comandos, em vez de perderem tempo a criarem um GUI :) .

Toda a gente (ou pelo menos a maior parte), que faz programas que correm da linha de comandos, necessita por vezes de passar argumentos quando executa um ficheiro (por exemplo "firefox -new-tab http://www.portugal-a-programar.org/forum/index.php").

Mas como é que se faz isso em Python?

Na realidade, existem 3 maneiras de o fazer. Iremos começar pela mais simples que é usando o módulo sys.

import sys

argumentos_passados = sys.argv[1:]

print argumentos_passados

O sys.argv é uma lista, que contém tudo o que é escrito quando o programa é iniciado (já vou explicar a razão para usar o [1:], ou seja, não contar com o primeiro valor) . Por exemplo, se gravarem este código num ficheiro (digamos, python_sys.py), e começarem a escrever coisas para a frente, o resultado que irão obter será aquilo que escreveram. Por exemplo:

rolando@rolando-desktop:~/Desktop$ python python_sys.py

[]

rolando@rolando-desktop:~/Desktop$

Isto é o que obtemos quando executamos o programa, mas sem lhe passar nenhuns argumentos, ele não imprime nada, pois não lhe passamos nada.

Agora vamos tentar outra vez.

rolando@rolando-desktop:~/Desktop$ python python_sys.py -v -e --dir ~/Desktop/porn

['-v', '-e', '--dir', '/home/rolando/Desktop/porn']

rolando@rolando-desktop:~/Desktop$

Como podem ver, recebemos uma lista com os atributos todos que passamos.

Mas é o que é o sys.argv[0]? Bem, isso é o nome do ficheiro! Para vermos isso, vamos modificar o programa um pouco.

import sys

nome_do_ficheiro = sys.argv[0]

argumentos_passados = sys.argv[1:]

print "O nome do ficheiro e: " + nome_do_ficheiro
print "E os argumentos passados sao: " + str(argumentos_passados)

NOTA: Lembrem-se que os argumentos_passados são uma lista, e por isso não podem adicionar directamente a uma string sem o converter primeiro para uma string também.

E agora vamos correr o programa.

rolando@rolando-desktop:~/Desktop$ python python_sys.py

O nome do ficheiro e: python_sys.py

E os argumentos passados sao: []

rolando@rolando-desktop:~/Desktop$

Se passarmos alguns argumentos, o efeito será como anteriormente.

rolando@rolando-desktop:~/Desktop$ python python_sys.py -v -e --dir ~/Desktop/porn

O nome do ficheiro e: python_sys.py

E os argumentos passados sao: ['-v', '-e', '--dir', '/home/rolando/Desktop/porn']

rolando@rolando-desktop:~/Desktop$

E se mudarmos o nome do ficheiro do programa?

rolando@rolando-desktop:~/Desktop$ mv python_sys.py o_meu_programa_leet.py

rolando@rolando-desktop:~/Desktop$ python o_meu_programa_leet.py

O nome do ficheiro e: o_meu_programa_leet.py

E os argumentos passados sao: []

rolando@rolando-desktop:~/Desktop$

Como podem ver, sempre que mudam o nome do ficheiro, o sys.argv[0] mudará também.

Apesar de o sys.argv ser o método mais simples de obter os argumentos, trabalhar com eles pode não ser o mais fácil. Basicamente terão que ter um for loop do estilo:

for argumento in range(0, len(argumentos_passados)):
   if argumentos_passados[argumento] == "-v":
       verbose = True

   if argumentos_passados[argumento] == "-e":
       export()

   if argumentos_passados[argumento] == "--dir" \
   and argumentos_passados[argumento + 1][0] != "-" \
   and argumentos_passados[argumento + 1][:1] != "--":
       directorio = argumento_passado[argumento + 1]

Depois do sys.argv, temos o módulo getopt. Infelizmente, nunca o usei muito, por isso o melhor é vocês verem a documentação oficial para o módulo aqui

Assim que tiver mais experiência, eu irei adicionar-lo ao tutorial.

Por fim, o outro método é usar o OptionParser, que está no módulo optparse, que é um método mais Object-Oriented.

from optparse import OptionParser

argv = OptionParser()

argv.add_option("-v", "--verbose", action = "store_true", dest = "verbose",
                   help = "Faz o programa mostrar mais informacao")

argv.add_option("-d", "--dir", action = "store", dest = "directorio", type ="string",
                   help = "Guarda o directorio")

(argumentos, palha_que_nao_interessa) = argv.parse_args()

Este método é diferente do outro, mas é também simples. Primeiro de tudo, temos que associar o OptionParser() a uma variável (neste caso, argv). Depois, vamos dando as nossas opções a essa variável, usando o método "add_option" e dizendo a opção que queremos nomear (por exemplo, "-v" ou "-d"), com a opção de dar-mos um argumento longo (daqueles que começam com "--"). Depois dissemos o que queremos fazer quando usarmos essa opção (por exemplo, "store_true", que faz com que uma variável tenha o valor True, ou o "store" que faz com que o valor que vier à frente seja guardado numa variável (exemplo: "-d ~/Desktop/porn" guarda o "~/Desktop/porn" numa variável)). Depois podemos dar o destino para onde queremos colocar o valor da opção (por exemplo, o True), para depois podermos aceder a ela (já explico como aceder às variáveis). Por fim, podemos definir uma mensagem de ajuda, pois o OptionParser cria automaticamente um argumento "-h" ou "--help", que mostra automaticamente, todas as strings "help" definidas.

Por fim, temos de usar o método "parse_args" em duas variáveis, para podermos aceder às opções.

A primeira variável (neste caso, "argumentos"), vai receber o valor das opções que encontrar. Por exemplo, se quiséssemos aceder ao valor da opção "-v" víamos que o seu destino é "verbose", logo para acedermos a ela, tínhamos que usar "argumentos.verbose", sendo que o mesmo seria para o "-d" (ou seja, "argumentos.directorio"). Caso exista opções passadas ao executar o programa, e que não tenham sido definidas pelo método "add_option", essas opções irão para a segunda variável (neste caso, convenientemente chamada de "palha_que_nao_interessa").

Sendo assim, caso corrermos o programa com as opções "--dir ~/Desktop/porn --eu_nao_existo", a variável "argumentos.directorio" teria o valor "~/Desktop/porn" e caso usassem um print na variável "palha_que_nao_interessa", veriam que a opção "--eu_nao_existo", estava lá, pois o programa não sabe o que fazer com ela.

O módulo ObjectParser, contém mais algumas opções, que podem ver aqui (contém um tutorial e tudo :D ).

Sendo assim, qual será a melhor opção a utilizar, da próxima vez que vocês tiveram a fazer um programa e queiram dar um funcionalidade na linha de comandos? Na minha opinião isso depende.

Caso queiram uma coisa mais rápida, e sem terem que se preocupar muito com a ordem com que os argumentos são dados, o melhor seria irem com o OptionParser.

Se no entanto, quiserem mais controlo sobre as opções, e não se importam de codar todas as pequenas coisas, acho que seria melhor usarem o sys.argv (penso que oferece um maior controlo sobre as opções).

E assim acabamos o tutorial.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ainda bem que te ajudou ;)

(Só tenho é que aprender a mexer mais no getopt, para depois adicionar aqui :()

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Belissimo artigo, Rolando2424

(eita que nick estranho, amigo! HUAHAUHAUHAUAHUAHAUHAU

Brincadeirinha rs..  :thumbsup:

Thanks

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora