Como faço para canalizar uma chamada de subprocesso para um arquivo de texto?

93
subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"])

Agora tenho um script que executo. Quando eu o executo e ele atinge essa linha, ele começa a imprimir coisas porque run.sh contém impressões.

Como posso canalizar isso para um arquivo de texto também? (E também imprima, se possível)

TIMEX
fonte

Respostas:

171

Se você deseja gravar a saída em um arquivo, pode usar o argumento- padrão de subprocess.call.

É preciso None,subprocess.PIPE um objeto de arquivo ou um descritor de arquivo. O primeiro é o padrão, stdout é herdado do pai (seu script). O segundo permite que você passe de um comando / processo para outro. A terceira e a quarta são o que você deseja, que a saída seja gravada em um arquivo.

Você precisa abrir um arquivo com algo semelhante opene passar o objeto ou o descritor inteiro do arquivo para call:

f = open("blah.txt", "w")
subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"], stdout=f)

Estou supondo que qualquer objeto válido do tipo arquivo funcionaria, como um soquete (suspiro :)), mas nunca tentei.

Como marcog menciona nos comentários, você pode querer redirecionar stderr também, você pode redirecionar isso para o mesmo local que stdout com stderr=subprocess.STDOUT. Qualquer um dos valores mencionados acima também funciona, você pode redirecionar para lugares diferentes.

Skurmedel
fonte
5
por que subprocess.call (["echo", "1", ">>", "t.txt"]) funciona?
StackOverflowOfficial
7
@Goldname você precisa de um shell para fazer o redirecionamento, então: subprocess.call(["echo", "1", ">>", "t.txt"], shell=True)deve funcionar.
Wes Mason
@WesMason Obrigado, mas achei que subprocess.call funcionava de uma maneira que era basicamente como copiar e colar no shell?
StackOverflowOfficial
2
@Goldname nah, tudo no subprocesso depende da classe Popen subjacente, que abre um processo, shell = True forçará o processo a ser executado no shell padrão do sistema (por exemplo, / bin / sh em sistemas POSIX, que geralmente é bash ou dash ), é mais seguro dessa forma, pois você não está aberto a todas as funcionalidades extras fornecidas pelo shell (uma linguagem de programação inteira em si mesma, com seus próprios exploits ao passar dados fornecidos pelo usuário). Além disso, shlex.quoteverifique se você está passando dados possivelmente sujos para um subshell.
Wes Mason
4
Devemos também fechar o arquivo depois de terminar? isso fechará o arquivo depois de terminarmos: with open("blah.txt","w") as f: subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml", "/tmp/video_xml"], stdout=f) @Skurmedel
alper
18

As opções para popenpodem ser usadas emcall

args, 
bufsize=0, 
executable=None, 
stdin=None, 
stdout=None, 
stderr=None, 
preexec_fn=None, 
close_fds=False, 
shell=False, 
cwd=None, 
env=None, 
universal_newlines=False, 
startupinfo=None, 
creationflags=0

Assim...

subprocess.call(["/home/myuser/run.sh", "/tmp/ad_xml",  "/tmp/video_xml"], stdout=myoutput)

Então você pode fazer o que quiser com myoutput (o que precisa ser um arquivo, aliás).

Além disso, você pode fazer algo mais próximo de uma saída canalizada como esta.

dmesg | grep hda

seria:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Há muitas informações úteis e adoráveis ​​na página de manual do python .

ocodo
fonte