Unindo Python e Bash: bibliotecas smart-env e python-shell.

Boa tarde a todos.

Atualmente, Python é uma das linguagens mais utilizadas na criação não apenas de produtos de software, mas também na infraestrutura que os suporta. Como resultado, muitos devops, por sua vontade ou não, tiveram que aprender uma nova linguagem para complementar seus antigos e bons scripts em Bash. No entanto, Bash e Python adotam abordagens diferentes para a escrita de código e possuem características específicas, por isso a portabilidade de scripts Bash para a 'linguagem da cobra' às vezes se torna uma tarefa complexa e longe de ser trivial.

Para facilitar a vida dos devops, muitas bibliotecas e utilitários úteis em Python foram criados e continuam a ser desenvolvidos. Este artigo descreve duas novas bibliotecas desenvolvidas pelo autor deste post — smart-env e python-shell — que têm como objetivo livrar os devops da necessidade de se preocupar muito com os detalhes de funcionamento do Python, abrindo espaço para tarefas mais interessantes. O campo de atuação das bibliotecas é variáveis de ambiente e execução de utilitários externos.

Quem estiver interessado, por favor, continue lendo.

Novos 'cavalos para a vitória'?

À primeira vista, por que criar novos pacotes para operações bastante comuns? O que impede o uso direto de os.environ e subprocess.?

As evidências em favor de cada uma das bibliotecas serão apresentadas separadamente.

Biblioteca smart-env

Antes de escrever sua própria criação, é útil pesquisar na Internet em busca de soluções prontas. Claro, há o risco de não encontrar o que precisa, mas isso é, na verdade, um 'caso de seguro'. Na maioria das vezes, essa abordagem funciona e economiza muito tempo e esforço.

Gartner, em 2016, a taxa de virtualização de muitas empresas superará 75%, e o mercado será avaliado em $5,6 bilhões. No entanto, existem certos fatores que impedem a disseminação generalizada da virtualização. Uma das principais razões continua a ser a complexidade da “reestruturação” dos data centers para um novo modelo de operação, uma vez que os custos frequentemente superam os benefícios potenciais. pesquisa foi identificado o seguinte:

  • existem pacotes que realmente encapsulam chamadas para os.environ, mas exigem muitas ações distrativas (criação de instâncias de classe, parâmetros especiais nas chamadas, etc.);
  • existem pacotes decentes que, no entanto, estão rigidamente ligados a um ecossistema específico (principalmente, a frameworks web como Django) e, portanto, não são universais sem ajustes;
  • existem raras tentativas de fazer algo novo. Por exemplo, adicionar tipagem e analisar explicitamente os valores das variáveis chamando métodos do tipo
    get_(var_name)

    Ou ainda uma outra solução, que, no entanto, não suporta o atualmente menosprezado Python 2 (no qual, apesar do R.I.P. oficial., ainda há montanhas de código escrito e ecossistemas inteiros);

  • existem projetos estudantis que inexplicavelmente acabaram no PyPI upstream e apenas criam problemas com a nomeação de novos pacotes (em particular, o nome "smart-env" é uma medida forçada).

E essa lista pode continuar por muito tempo. No entanto, os pontos mencionados acima foram suficientes para acender a ideia de criar algo prático e universal.

Os requisitos estabelecidos para a criação do smart-env:

  • Um esquema de uso o mais simples possível
  • Suporte a tipagem de dados facilmente configurável
  • Compatibilidade com Python 2.7
  • Boa cobertura de código com testes

No final das contas, tudo isso foi implementado com sucesso. Aqui está um exemplo de uso:

from smart_env import ENV

print(ENV.HOME)  # Equivale a print(os.environ['HOME'])

# supondo que você tenha configurado a variável de ambiente MYVAR para "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Equivale a booleano True

ENV.NEW_VAR = 100  # Define uma nova variável de ambiente

Como pode ser visto no exemplo, para trabalhar com a nova classe, basta importá-la (não é necessário criar uma instância — menos uma ação desnecessária). O acesso a qualquer variável de ambiente é feito referindo-se a ela como uma variável da classe ENV, o que, na verdade, torna essa classe uma camada intuitiva sobre o ambiente de sistema nativo, enquanto a transforma em uma possibilidade de objeto de configuração para praticamente qualquer sistema (uma abordagem semelhante, por exemplo, é alcançada no Django, onde o objeto de configuração é diretamente o módulo/pacote settings).

Ativar/desativar o modo de suporte à tipagem automática é alcançado através do uso de dois métodos — enable_automatic_type_cast() e disable_automatic_type_cast(). Isso pode ser conveniente se uma variável de ambiente contiver um objeto JSON-serializado ou até mesmo apenas uma constante booleana (o uso explícito da variável DEBUG no Django através da comparação da variável de ambiente com strings "permitidas" é um dos casos mais comuns). Mas agora não há necessidade de converter strings explicitamente — a maior parte das ações necessárias já está integrada nas entranhas da biblioteca, aguardando apenas o sinal para atuar. 🙂 No geral, a tipagem funciona de forma transparente e suporta quase todos os tipos de dados embutidos disponíveis (não foram testados frozenset, complex e bytes).

A exigência de suporte ao Python 2 foi implementada praticamente sem sacrifícios (abandonando o typing e alguns "guloseimas" das versões mais recentes do Python 3), em particular, graças ao onipresente six (para resolver problemas de uso de metaclasses).

Mas há algumas limitações:

  • O suporte ao Python 3 pressupõe a versão 3.5 ou superior (a sua presença no seu projeto é resultado de preguiça ou da falta de necessidade de melhorias, pois é difícil imaginar uma razão objetiva para você ainda estar na 3.4);
  • No Python 2.7, a biblioteca não suporta a desserialização de literais de conjuntos. Descrição aqui. Mas, se alguém quiser implementar — seja bem-vindo:);

A biblioteca também adota um mecanismo de exceções para casos de erros de parsing. Se uma string não puder ser reconhecida por nenhum dos analisadores disponíveis, o valor permanece como string (mais por questões de conveniência e compatibilidade com a lógica habitual de variáveis no Bash).

Biblioteca python-shell

Agora vou falar sobre a segunda biblioteca (omitirei a descrição das deficiências das alternativas existentes — é semelhante à descrita para smart-env. As alternativas são — aqui e aqui).

Em geral, a ideia de implementação e os requisitos são análogos aos descritos para smart-env, como pode ser visto no exemplo:

from python_shell import Shell

Shell.ls('-l', '$HOME')  # Igual a "ls -l $HOME"

command = Shell.whoami()  # Igual a "whoami"
print(command.output)  # imprime seu nome de usuário atual

print(command.command)  # imprime "whoami"
print(command.return_code)  # imprime "0"
print(command.arguments)  # imprime ""

Shell.mkdir('-p', '\/tmp\/new_folder')  # cria uma nova pasta

A ideia é a seguinte:

  1. Uma classe única, personificando o Bash no mundo Python;
  2. Cada comando Bash é chamado como uma função da classe Shell;
  3. Os parâmetros de chamada de cada função são passados para a respectiva chamada do comando Bash;
  4. Cada comando é executado "aqui e agora" no momento de sua chamada, ou seja, utiliza-se uma abordagem síncrona;
  5. Há a possibilidade de acessar a saída do comando em stdout, bem como seu código de retorno;
  6. Se o comando não existir no sistema — uma exceção é lançada.

Assim como no caso do smart-env, o suporte ao Python 2 é assegurado (embora tenha exigido um pouco mais de sacrifício) e não há suporte para Python 3.0-3.4.

Planos de desenvolvimento das bibliotecas

As bibliotecas podem ser utilizadas já: ambas estão disponíveis no PyPI oficial. Os códigos-fonte estão disponíveis no Github (veja abaixo).

Ambas as bibliotecas vão se desenvolver com base no feedback coletado dos interessados. E, se em smart-env pode ser difícil pensar em uma variedade de novas funcionalidades, em python-shell certamente há mais a acrescentar:

  • suporte a chamadas não bloqueantes;
  • capacidade de comunicação interativa com a equipe (trabalho com stdin);
  • adição de novas propriedades (por exemplo, propriedade para obter a saída do stderr);
  • implementação de um catálogo de comandos disponíveis (para uso com a função dir());
  • etc.

Links

  1. Biblioteca smart-env: Github e PyPI
  2. Biblioteca python-shell: Github e PyPI
  3. Canal do Telegram atualizações das bibliotecas

UPD 23.02.2020:
* Repositórios transferidos, links correspondentes atualizados
* A versão python-shell==1.0.1 está prevista para ser lançada em 29.02.2020. As mudanças incluem suporte à autocompletação de comandos e ao comando dir(Shell), execução de comandos com identificadores inválidos em Python, correção de bugs.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster