Fazemos amigos Python e Bash: bibliotecas smart-env e python-shell

Bom Dia a todos.

Hoje, o Python é uma das linguagens mais usadas no campo de criação não apenas diretamente de produtos de software, mas também de fornecer sua infraestrutura. Como resultado, muitos devops, por sua vontade ou contra, tiveram que aprender um novo idioma para uso posterior como complemento dos bons e antigos scripts do Bash. No entanto, Bash e Python professam abordagens diferentes para escrever código e têm certos recursos, tendo em vista que transportar scripts Bash para a "linguagem de cobra" às vezes é amplo e longe de uma tarefa trivial.

Para facilitar a vida dos desenvolvedores, muitas bibliotecas e utilitários úteis no Python foram criados e continuam sendo criados. Este artigo descreve imediatamente duas novas bibliotecas criadas pelo autor desta postagem - smart-enve python-shell - e projetados para salvar os devops da necessidade de prestar muita atenção aos meandros do trabalho com o Python, deixando espaço para tarefas mais interessantes. O escopo da biblioteca é de variáveis ​​de ambiente e o lançamento de utilitários externos.

Quem estiver interessado, por favor, sob o gato.

Bicicletas novas?


Parece, por que criar novos pacotes para operações bastante mundanas? O que impede o uso direto de os.environ e subprocesso. <Método ou classe de sua escolha>?

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

Biblioteca Smart-env


Antes de escrever sua própria ideia, é útil navegar na Internet e procurar soluções prontas. Obviamente, existe o risco de não encontrar o que você precisa, mas é um "caso de seguro". Como regra, a abordagem funciona e economiza muito tempo e esforço.

De acordo com os resultados da pesquisa , foram revelados os seguintes:

  • existem pacotes que realmente atendem chamadas ao os.environ, mas ao mesmo tempo exigem várias ações de distração (criação de uma instância da classe, parâmetros especiais nas chamadas, etc.);
  • existem bons pacotes, no entanto, fortemente vinculados a um ecossistema específico (principalmente frameworks da web como o Django) e, portanto, não são universais sem um arquivo;
  • existem raras tentativas de fazer algo novo. Por exemplo, adicione digitação e analise explicitamente os valores das variáveis ​​chamando métodos do formulário

    get_<typename>(var_name)

    Ou aqui está outra solução que, no entanto, atualmente não suporta Python 2 desonrado (em que, apesar do RIP oficial , ainda existem montanhas de código escrito e ecossistemas inteiros);
  • existem trabalhos escolares e para estudantes, não está claro por que eles acabaram no PyPI upstream e apenas criam problemas ao nomear novos pacotes (em particular, o nome "smart-env" é uma medida necessária).

E a lista continua. No entanto, os pontos acima foram suficientes para captar a idéia de tornar algo conveniente e universal.

Requisitos para smart-env:

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

No final, 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 a nova classe, basta importá-la (você não precisa 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 essa classe um invólucro intuitivo para o ambiente do sistema nativo, transformando-a simultaneamente em uma possível variante do objeto de configuração de praticamente qualquer sistema (uma abordagem semelhante, por exemplo, é alcançada no Django , apenas lá o objeto de configuração é diretamente o pacote de módulo / configurações).

A ativação / desativação do modo de suporte de digitação automática é realizada 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 JSON serializado ou mesmo apenas uma constante booleana (configurar explicitamente a variável DEBUG no Django, comparando a variável de ambiente com cadeias "válidas" é um dos casos mais comuns). Mas agora não há necessidade de converter explicitamente as linhas - a maioria das ações necessárias já estão incorporadas nas entranhas da biblioteca e estão apenas aguardando um sinal de ação. :) Em geral, a digitação funciona de forma transparente e suporta quase todos os tipos de dados internos disponíveis (frozenset, complex e bytes não foram testados).

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

Mas existem algumas limitações:

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

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

Biblioteca Python-shell


Agora vou falar sobre a segunda biblioteca (vou omitir a descrição das deficiências dos análogos disponíveis - é semelhante à descrita para o ambiente inteligente. Análogos aqui e aqui ).

Em geral, a idéia de implementação e os requisitos são semelhantes aos descritos para o 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 em função da classe Shell;
  3. Os parâmetros de chamada de cada função são então encaminhados para a chamada para o comando Bash correspondente;
  4. Cada comando é executado "aqui e agora" no momento da sua chamada, ou seja, trabalha abordagem síncrona;
  5. é possível acessar o comando de escape no stdout, bem como seu código de retorno;
  6. Se o comando estiver ausente no sistema, uma exceção será lançada.

Como no smart-env, o suporte ao Python 2 é fornecido (embora tenha levado um pouco mais de sangue sacrificial) e não há suporte ao Python 3.0-3.4.

Planos de Desenvolvimento de Bibliotecas


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

As duas bibliotecas serão desenvolvidas levando em consideração o feedback coletado dos interessados. E, se no ambiente inteligente, pode ser difícil criar uma variedade de novos recursos, definitivamente há mais alguma coisa a ser adicionada no python-shell:

  • suporte para chamadas sem bloqueio;
  • a possibilidade de comunicação interativa com a equipe (trabalho com stdin);
  • adicionando novas propriedades (por exemplo, propriedades para obter escape do stderr);
  • implementação do catálogo de comandos disponíveis (para uso com a função dir ());
  • etc.

Referências


  1. Biblioteca Smart-env: Github e PyPI
  2. Biblioteca Python-shell: github e pypi
  3. Canal de telegrama para atualizações da biblioteca


UPD 23/02/2020:
* 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. Entre as mudanças estão o suporte ao preenchimento automático de comandos e o comando dir (Shell), o lançamento de comandos com um identificador inválido do Python e correções de erros.

UPD 03/01/2020:
* Publique no próximo lançamento.

All Articles