piping valor da variável python para o script bash (dentro do script python)

1

Após anos de bash scripting, tenho a tarefa de modificar um script python para que ele chame um shell script quando certas condições forem atendidas. Essa parte não foi muito ruim, mas agora eu estou tentando também enviar este script de shell uma variável de dentro do script python e estou me perdendo.

O shell script pega stdin, que é onde eu estou tentando colocar o valor da variável python, que é apenas um inteiro.

meu código (até agora) é assim:

if VAR > NUMBER:
import os
bashCommand = "echo something | /path/to/script --args"
os.system(bashCommand) 

e funciona muito bem. Mas o que eu quero fazer é tornar os.system (bashCommand) um equivalente a:

echo $VAR | /path/to/script --args

ou até mesmo

echo 'some text' $VAR | /path/to/script --args

dada a maneira como os.system parece funcionar, parece que estou me aproximando completamente disso.

Então, eu acho que minha pergunta é como posso passar o valor de VAR para bashCommand, preferencialmente como stdin?

    
por kadamwolfe 03.09.2015 / 20:28

4 respostas

1

O Python não expande variáveis em strings da mesma maneira que o bash. Se você tem VAR em python e quer passar isso para o bash você poderia fazer

subprocess.call('echo {} | /path/to/script --args'.format(VAR), shell=True)

se VAR em python tiver o nome de uma variável bash que você deseja expandir, você poderá fazer algo semelhante:

subprocess.call('echo "${}" | /path/to/script --args'.format(VAR), shell=True)
    
por 03.09.2015 / 20:38
3

Não use os.system() , ele está obsoleto em favor de subprocess module.

No seu caso, você pode usar o módulo subprocess diretamente e é melhor não usar o parâmetro shell=True , pois isso não é seguro para executar comandos diretamente no shell. Todas as funcionalidades que você precisa aqui, como pipe, podem ser emuladas pelo módulo subprocess .

Vamos pegar este exemplo:

import subprocess
var = 'foobar'

first = subprocess.Popen(['/bin/echo', var], stdout=subprocess.PIPE)
second = subprocess.Popen(['bash', '/path/to/script', '--args'], stdin=first.stdout)

definimos uma variável var , depois usamos a classe subprocess.Popen para obter o valor de var usando /bin/echo e, em seguida, enviamos esse valor para o canal. O first é um objeto da classe subprocess.Popen .

Em seguida, usamos o STDOUT de first como STDIN de second via pipe e executamos o script bash de acordo.

Se você quiser salvar a saída de um comando como uma string, use subprocess.check_output function em vez de. :

second = subprocess.check_output(['bash', '/path/to/script', '--args'], stdin=first.stdout)

Leia a documentação oficial do módulo de subprocesso para obter mais ideias.

    
por 03.09.2015 / 21:10
0

A chamada de os.system() está obsoleta, embora ainda seja válida. Essa funcionalidade pode estar indo embora no futuro (provavelmente será), portanto, convém considerar seriamente refatorar essas chamadas com o módulo subprocess , que tem uma maneira muito fácil de enviar dados para STDIN de um subprocesso e ler de seu STDOUT. link

    
por 03.09.2015 / 20:33
0

Eu acho que a boa prática é:

var = subprocess.Popen(['/bin/echo', var], stdout=subprocess.PIPE)
second = subprocess.Popen(['bash', '/path/to/script', '--args'],stdin=var.stdout, stdout=subprocess.PIPE)
var.stdout.close()
output = second.communicate()[0]
var.wait()
    
por 08.03.2016 / 12:47