Fazendo amizade entre Python e Bash: bibliotecas smart-env e python-shell

Bom dia a todos.

Hoje, Python é uma das linguagens mais utilizadas na área de criação não apenas de produtos de software, mas também de fornecimento de sua infraestrutura. Como resultado, muitos devops, por sua vontade ou contra ela, tiveram que aprender uma nova linguagem para uso posterior como complemento aos bons e velhos scripts Bash. No entanto, Bash e Python professam abordagens diferentes para escrever código e possuem certos recursos, o que significa que portar scripts Bash para a “linguagem cobra” às vezes acaba sendo uma tarefa ampla e nada trivial.

Para facilitar a vida dos devops, muitas bibliotecas e utilitários úteis em Python foram criados e continuam a ser criados. Este artigo descreve duas novas bibliotecas criadas pelo autor deste post - ambiente inteligente и python-shell - e projetado para aliviar os devops da necessidade de prestar muita atenção às complexidades de trabalhar com Python, deixando espaço para tarefas mais interessantes. O escopo de atividade das bibliotecas são variáveis ​​de ambiente e lançamento de utilitários externos.

Quem estiver interessado, consulte gato.

Novas "bicicletas"?

Ao que parece, por que criar novos pacotes para operações bastante comuns? O que impede você de usar os.environ e subprocess.<método ou classe de sua escolha> diretamente?

Fornecerei evidências a favor de cada uma das bibliotecas separadamente.

biblioteca de ambiente inteligente

Antes de escrever sua própria ideia, é útil acessar a Internet e procurar soluções prontas. Claro que existe o risco de não encontrar o que precisa, mas trata-se antes de um “evento segurado”. Via de regra, essa abordagem funciona e economiza muito tempo e esforço.

De acordo com os resultados motor de busca foi revelado o seguinte:

  • existem pacotes que realmente agrupam chamadas para os.environ, mas ao mesmo tempo exigem várias ações de distração (criação de uma instância de classe, parâmetros especiais em chamadas, etc.);
  • Existem bons pacotes, que, no entanto, estão estritamente vinculados a um ecossistema específico (principalmente frameworks web como Django) e, portanto, não são de todo universais sem um arquivo;
  • há raras tentativas de fazer algo novo. Por exemplo, adicionar digitação e analisar explicitamente os valores das variáveis ​​​​chamando métodos como
    get_<typename>(var_name)

    Ou aqui mais uma solução, que, no entanto, não suporta o agora desgraçado Python 2 (que, apesar RIP oficial, ainda existem montanhas de códigos escritos e ecossistemas inteiros);

  • existem trabalhos escolares que, por alguma razão desconhecida, acabaram no PyPI upstream e apenas criam problemas com a nomenclatura de novos pacotes (em particular, o nome “smart-env” é uma medida necessária).

E essa lista pode durar muito tempo. No entanto, os pontos acima foram suficientes para me entusiasmar com a ideia de fazer algo conveniente e universal.

Requisitos que foram definidos antes de escrever o smart-env:

  • O esquema de uso mais simples
  • Suporte para digitação de dados facilmente configurável
  • Compatível com Python 2.7
  • Boa cobertura de código por testes

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

from smart_env import ENV

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

# assuming you set env variable MYVAR to "True"

ENV.enable_automatic_type_cast()

my_var = ENV.MY_VAR  # Equals boolean True

ENV.NEW_VAR = 100  # Sets a new environment variable

Como você pode ver no exemplo, para trabalhar com uma nova classe, basta importá-la (não é necessário criar uma instância - menos a ação extra). O acesso a qualquer variável de ambiente é obtido referindo-se a ela como uma variável da classe ENV, o que, de fato, torna esta classe um wrapper intuitivo para o ambiente nativo do sistema, ao mesmo tempo que a transforma em um possível objeto de configuração para quase qualquer sistema ( uma abordagem semelhante, por exemplo, é alcançada no Django, só que lá o objeto de configuração é o próprio módulo/pacote de configurações).

A ativação/desativação do modo de suporte à digitação automática é obtida usando dois métodos - enable_automatic_type_cast() e disable_automatic_type_cast(). Isso pode ser conveniente se a variável de ambiente contiver um objeto serializado semelhante a JSON ou mesmo apenas uma constante booleana (definir explicitamente a variável DEBUG no Django comparando a variável de ambiente com strings “válidas” é um dos casos mais comuns). Mas agora não há necessidade de converter strings explicitamente - a maioria das ações necessárias já estão incorporadas nas profundezas da biblioteca e estão apenas aguardando um sinal para agir. 🙂 Em geral, a digitação funciona de forma transparente e suporta quase todos os tipos de dados integrados disponíveis (frozenset, complexo e bytes não foram testados).

O requisito de suporte ao Python 2 foi implementado praticamente sem sacrifícios (o abandono da digitação e alguns dos “doces” das versões mais recentes do Python 3), em particular, graças aos onipresentes seis (para resolver os problemas de uso de metaclasses ).

Mas existem algumas restrições:

  • Suporte ao Python 3 significa versão 3.5 e superior (a presença deles em seu projeto é resultado de preguiça ou falta de necessidade de melhorias, já que é difícil encontrar uma razão objetiva pela qual você ainda está no 3.4);
  • No Python 2.7, a biblioteca não oferece suporte à desserialização de literais definidos. Descrição aqui. Mas se alguém quiser implementar, seja bem-vindo :);

A biblioteca também possui um mecanismo de exceção em caso de erros de análise. Se a string não puder ser reconhecida por nenhum dos analisadores disponíveis, o valor permanecerá uma string (em vez disso, por razões de conveniência e compatibilidade com versões anteriores com a lógica usual de como as variáveis ​​funcionam no Bash).

biblioteca python-shell

Agora vou falar sobre a segunda biblioteca (omitirei a descrição das deficiências dos análogos existentes - é semelhante ao descrito para smart-env. Análogos - aqui и aqui).

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

from python_shell import Shell

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

command = Shell.whoami()  # Equals "whoami"
print(command.output)  # prints your current user name

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

Shell.mkdir('-p', '/tmp/new_folder')  # makes a new folder

A ideia é esta:

  1. Uma única classe que representa o Bash no mundo Python;
  2. Cada comando Bash é chamado como uma função da classe Shell;
  3. Os parâmetros para cada chamada de função são então passados ​​para a chamada de comando Bash correspondente;
  4. Cada comando é executado “aqui e agora” no momento em que é chamado, ou seja, a abordagem síncrona funciona;
  5. é possível acessar a saída de um comando em stdout, bem como seu código de retorno;
  6. Se o comando não estiver no sistema, uma exceção será lançada.

Tal como acontece com o smart-env, há suporte para Python 2 (embora tenha sido necessário um pouco mais de sangue sacrificial) e nenhum suporte para Python 3.0-3.4.

Planos de desenvolvimento de biblioteca

Você pode usar as bibliotecas agora: ambas estão publicadas no PyPI oficial. As fontes estão disponíveis no Github (veja abaixo).

Ambas as bibliotecas serão desenvolvidas tendo em conta o feedback recolhido dos interessados. E, se for difícil criar uma variedade de novos recursos no smart-env, então no python-shell definitivamente há algo mais a adicionar:

  • suporte para chamadas sem bloqueio;
  • possibilidade de comunicação interativa com a equipe (trabalhando com stdin);
  • adição de novas propriedades (por exemplo, propriedade para receber saída de stderr);
  • implementação de um diretório de comandos disponíveis (para uso com a função dir());
  • и т.д.

referências

  1. biblioteca de ambiente inteligente: Github и PyPI
  2. biblioteca python-shell: Github и PyPI
  3. Canal Telegram atualizações da biblioteca

UPD 23.02.2020:
* Os repositórios foram movidos, os links correspondentes foram atualizados
* A versão python-shell==1.0.1 está sendo preparada para lançamento em 29.02.2020/XNUMX/XNUMX. As alterações incluem suporte para preenchimento automático de comando e comando dir(Shell), execução de comandos com um identificador Python inválido e correções de bugs.

Fonte: habr.com

Adicionar um comentário