Precisa executar seus scripts Python com argumentos inseridos diretamente na linha de comando? Este guia detalha como analisar esses argumentos usando os módulos `sys`, `getopt` e `argparse` do Python.
Em Python, a função `input()` geralmente lida com a entrada do usuário. No entanto, algumas aplicações demandam que argumentos específicos sejam fornecidos no momento da execução do script, através da linha de comando.
Neste tutorial, você aprenderá a criar scripts Python que aceitam e processam opções e argumentos passados via linha de comando. Exploraremos os módulos internos do Python para realizar esta análise de forma eficiente.
Vamos começar!
Entendendo `sys.argv` em Python
Programadores familiarizados com C sabem que a linha de comando é uma forma comum de passar argumentos para um programa. Em C, isso é feito através da estrutura da função `main`:
#include<stdio.h> int main(int argc, char **argv){ //argc: contagem de argumentos //argv: vetor de argumentos //processamento dos argumentos return 0; }
Onde `argc` representa a contagem dos argumentos e `argv` é um vetor que contém esses argumentos.
Executando scripts Python com argumentos de linha de comando
Para executar um script Python na linha de comando, usa-se `python3 nome_do_arquivo.py`. É possível passar múltiplos argumentos juntamente com este comando:
$ python3 nome_do_arquivo.py arg1 arg2 ... argn
O módulo `sys` oferece ferramentas para acessar e tratar esses argumentos. `sys.argv` é uma lista que armazena todos os argumentos fornecidos na linha de comando.
Por exemplo, ao executarmos `main.py` com argumentos:
$ python3 main.py ola mundo script python
Podemos iterar sobre o vetor de argumentos usando um loop `for` e a função `enumerate`:
# main.py import sys for idx, arg in enumerate(sys.argv): print(f"arg{idx}: {arg}")
# Saída arg0:main.py arg1:ola arg2:mundo arg3:script arg4:python
O primeiro argumento (índice 0) é sempre o nome do script. Os argumentos seguintes começam a partir do índice 1.
Este é um programa básico que recebe e processa argumentos de linha de comando. No entanto, ele apresenta algumas limitações:
- Como o usuário sabe quais argumentos deve inserir?
- Qual é o significado de cada um desses argumentos?
Para lidar com essas questões, podemos utilizar os módulos `getopt` ou `argparse`, como veremos a seguir. ✅
Análise de argumentos de linha de comando com `getopt`
Vamos explorar como analisar argumentos de linha de comando usando o módulo `getopt`.
Após importar `getopt`, é possível definir quais argumentos o script aceitará, junto com suas opções curtas e longas. Precisamos analisar os argumentos a partir do índice 1 em `sys.argv`, ou seja, `sys.argv[1:]`.
Suponha que necessitemos de uma string para mensagem e um nome de arquivo. Usaremos `m` e `f` como opções curtas, e `mensagem` e `arquivo` como opções longas.
Mas como especificar que uma opção requer um argumento?
- Em opções curtas, use dois pontos (:) após o nome da opção.
- Em opções longas, utilize um sinal de igual (=) após a opção.
Incorporando isso ao nosso código, o `main.py` se torna:
# main.py import sys from getopt import getopt opts, args = getopt(sys.argv[1:],'m:f:',['mensagem=','arquivo=']) print(opts) print(args)
A variável `opts` conterá as opções e argumentos em formato de tuplas. Argumentos posicionais adicionais serão armazenados em `args`.
Para executar o script, podemos fornecer a mensagem e o nome do arquivo usando opções curtas ou longas.
Executando `main.py` com opções longas:
$ python3 main.py --mensagem ola --arquivo algumarquivo.txt
As opções e argumentos são armazenados como tuplas em `opts`. Como não inserimos argumentos posicionais, `args` é uma lista vazia.
# Saída [('--mensagem', 'ola'), ('--arquivo', 'algumarquivo.txt')] []
De forma equivalente, podemos usar opções curtas:
$ python3 main.py -m ola -f algumarquivo.txt
# Saída [('-m', 'ola'), ('-f', 'algumarquivo.txt')] []
⚠️ A opção curta `-m` não deve ser confundida com o sinalizador `-m` usado para executar um módulo ao rodar um script Python.
Por exemplo, `python3 -m unittest main.py` executa `unittest` como módulo principal ao executar `main.py`.
Como mencionado, argumentos posicionais são coletados na variável `args`. Veja o exemplo:
$ python3 main.py -m ola -f algumarquivo.txt outro_argumento
A lista `args` contém o argumento posicional `outro_argumento`.
# Saída [('-m', 'ola'), ('-f', 'algumarquivo.txt')] ['outro_argumento']
Podemos iterar sobre a lista de tuplas `opts`, desempacotar cada tupla e extrair os argumentos correspondentes às opções.
O que faremos com o nome do arquivo e a mensagem? Vamos abrir o arquivo em modo de escrita e salvar a mensagem convertida para letras maiúsculas.
# main.py import sys from getopt import getopt opts, args = getopt(sys.argv[1:],'m:f:',['mensagem=','arquivo=']) print(opts) print(args) for option, argument in opts: if option == "-m": message = argument if option == '-f': file = argument with open(file,'w') as f: f.write(message.upper())
Executando `main.py` com opções curtas:
$ python main.py -m ola -f este_arquivo.txt [('-m', 'ola'), ('-f', 'este_arquivo.txt')] []
Após a execução, `este_arquivo.txt` é criado no diretório e contém a string `OLA`.
$ ls main.py este_arquivo.txt
$ cat este_arquivo.txt OLA
Como analisar argumentos de linha de comando com `argparse`
O módulo `argparse`, também parte da biblioteca padrão, é mais avançado para análise de argumentos e criação de interfaces de linha de comando.
Para iniciar, importamos a classe `ArgumentParser`:
from argparse import ArgumentParser arg_parser = ArgumentParser()
Vamos adicionar dois argumentos de linha de comando:
- `mensagem`: a string da mensagem.
- `arquivo`: o nome do arquivo a ser utilizado.
Usamos o método `add_argument()` para adicionar esses argumentos. A opção `help` permite adicionar descrições para cada argumento.
arg_parser.add_argument('mensagem',help='string da mensagem') arg_parser.add_argument('arquivo',help='nome do arquivo')
Com o `ArgumentParser` instanciado e argumentos adicionados, usamos `parse_args()` para obter os valores dos argumentos, armazenando o namespace em `args`. Acessamos cada valor com `args.nome_do_argumento`.
Depois, escrevemos a mensagem com letras maiúsculas e minúsculas trocadas (usando `swapcase()`) no arquivo.
args = arg_parser.parse_args() message = args.mensagem file = args.arquivo with open(file,'w') as f: f.write(message.swapcase())
O código completo do `main.py` é:
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('mensagem',help='string da mensagem') arg_parser.add_argument('arquivo',help='nome do arquivo') args = arg_parser.parse_args() print(args) message = args.mensagem file = args.arquivo with open(file,'w') as f: f.write(message.swapcase())
Entendendo o uso de argumentos de linha de comando
Para verificar como usar os argumentos, utilize a opção `–help`:
$ python3 main.py --help usage: main.py [-h] mensagem arquivo positional arguments: mensagem string da mensagem arquivo nome do arquivo optional arguments: -h, --help show this help message and exit
Não há argumentos opcionais, e ambos `mensagem` e `arquivo` são argumentos posicionais obrigatórios. Use `-h` para o mesmo efeito:
$ python3 main.py -h usage: main.py [-h] mensagem arquivo positional arguments: mensagem string da mensagem arquivo nome do arquivo optional arguments: -h, --help show this help message and exit
Se você não fornecer todos os argumentos, haverá um erro.
No exemplo abaixo, fornecemos um argumento (`Olá`), mas não o argumento do arquivo:
$ python3 main.py Olá usage: main.py [-h] mensagem arquivo main.py: error: the following arguments are required: arquivo
Ao fornecer os dois argumentos, o namespace `args` contém os valores:
$ python3 main.py Olá arquivo1.txt
# Saída Namespace(arquivo="arquivo1.txt", mensagem="Olá")
O script cria `arquivo1.txt`:
$ ls arquivo1.txt main.py
O arquivo contém `oLÁ`, que é `Olá` com letras maiúsculas e minúsculas trocadas.
$ cat arquivo1.txt oLÁ
Como tornar opcionais os argumentos da linha de comando
Para tornar argumentos opcionais, prefixe o nome com `–`.
Modificando `main.py`:
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('--mensagem',help='string da mensagem') arg_parser.add_argument('--arquivo',help='nome do arquivo')
Como são opcionais, podemos definir valores padrão:
if args.mensagem and args.arquivo: message = args.mensagem file = args.arquivo else: message="Python3" file="meuarquivo.txt"
O `main.py` completo:
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('--mensagem',help='string da mensagem') arg_parser.add_argument('--arquivo',help='nome do arquivo') args = arg_parser.parse_args() print(args) if args.mensagem and args.arquivo: message = args.mensagem file = args.arquivo else: message="Python3" file="meuarquivo.txt" with open(file,'w') as f: f.write(message.swapcase())
Verificando o uso, ambos são opcionais:
$ python3 main.py --help usage: main.py [-h] [--mensagem MENSAGEM] [--arquivo ARQUIVO] optional arguments: -h, --help show this help message and exit --mensagem MENSAGEM string da mensagem --arquivo ARQUIVO nome do arquivo
$ python3 main.py
O arquivo e mensagem no namespace `args` são `None`.
# Saída Namespace(arquivo=None, mensagem=None)
O script usa os valores padrão, `meuarquivo.txt` e `Python3`. O arquivo é criado:
$ ls arquivo1.txt main.py meuarquivo.txt
E contém `pYTHON3`.
$ cat meuarquivo.txt pYTHON3
É possível usar os argumentos `–mensagem` e `–arquivo` para melhor legibilidade:
$ python3 main.py --mensagem Programando --arquivo arquivo2.txt
# Saída Namespace(arquivo="arquivo2.txt", mensagem="Programando")
`arquivo2.txt` é criado no diretório:
$ ls arquivo1.txt arquivo2.txt main.py meuarquivo.txt
E contém `pROGRAMANDO`.
$ cat arquivo2.txt pROGRAMANDO
Conclusão
Resumindo:
- Em Python, acessamos argumentos de linha de comando usando `sys.argv`. `sys.argv[0]` é o nome do script, e os argumentos começam em `sys.argv[1:]`.
- Para legibilidade e opções, use `getopt` ou `argparse`.
- `getopt` analisa argumentos a partir do índice 1, permitindo definir opções curtas e longas.
- Use `:` e `=` para especificar que opções aceitam argumentos.
- Com `argparse`, instancie `ArgumentParser` e use `add_argument()` para argumentos posicionais. Use `–` para torná-los opcionais.
- Para recuperar os valores, chame `parse_args()`.
Em seguida, aprenda como realizar hashing seguro em Python.