Preciso executar um comando shell de forma assíncrona de um script Python. Com isso, quero dizer que quero que meu script Python continue em execução enquanto o comando externo dispara e faz tudo o que precisa ser feito.
Eu li esta postagem:
Então saí e fiz alguns testes, e parece que os.system()
vou fazer o trabalho desde que eu use &
no final do comando para não ter que esperar o retorno. O que me pergunto é se essa é a maneira correta de realizar tal coisa. Tentei commands.call()
mas não funcionou para mim porque bloqueia no comando externo.
Informe-me se os.system()
é aconselhável usar para isso ou se devo tentar alguma outra rota.
fonte
Se você deseja executar muitos processos em paralelo e, em seguida, manipulá-los quando eles gerarem resultados, você pode usar a pesquisa como a seguir:
O fluxo de controle é um pouco complicado porque estou tentando torná-lo pequeno - você pode refatorar a seu gosto. :-)
Isso tem a vantagem de atender primeiro às solicitações de finalização antecipada. Se você chamar
communicate
o primeiro processo em execução e ele for executado por mais tempo, os outros processos em execução ficarão parados, ociosos, quando você poderia estar lidando com seus resultados.fonte
os.waitpid
diretamente o que permite verificar se algum processo filho mudou de status.['/usr/bin/my_cmd', '-i', path]
vez de['/usr/bin/my_cmd', '-i %s' % path]
O que estou querendo saber é se este [os.system ()] é a maneira correta de fazer isso?
Não. Não
os.system()
é a maneira correta. É por isso que todo mundo diz para usarsubprocess
.Para obter mais informações, leia http://docs.python.org/library/os.html#os.system
fonte
Tive bom sucesso com o módulo asyncproc , que lida muito bem com a saída dos processos. Por exemplo:
fonte
Usar o pexpect com linhas de leitura sem bloqueio é outra maneira de fazer isso. O Pexpect resolve os problemas de deadlock, permite que você execute facilmente os processos em segundo plano e oferece maneiras fáceis de ter callbacks quando o seu processo gera strings predefinidas e geralmente torna a interação com o processo muito mais fácil.
fonte
Considerando "Não tenho que esperar que volte", uma das soluções mais fáceis será esta:
Mas ... Pelo que li, esta não é "a maneira correta de realizar tal coisa" por causa dos riscos de segurança criados por
subprocess.CREATE_NEW_CONSOLE
flag.As principais coisas que acontecem aqui é o uso de
subprocess.CREATE_NEW_CONSOLE
para criar um novo console e.pid
(retorna o ID do processo para que você possa verificar o programa mais tarde se desejar) para não esperar que o programa termine seu trabalho.fonte
Tenho o mesmo problema ao tentar me conectar a um terminal 3270 usando o software de script s3270 em Python. Agora estou resolvendo o problema com uma subclasse de Processo que encontrei aqui:
http://code.activestate.com/recipes/440554/
E aqui está a amostra retirada do arquivo:
fonte
A resposta aceita é muito antiga.
Encontrei uma resposta moderna melhor aqui:
https://kevinmccarthy.org/2016/07/25/streaming-subprocess-stdin-and-stdout-with-asyncio-in-python/
e fez algumas alterações:
É improvável que os comandos de exemplo funcionem perfeitamente em seu sistema e não lida com erros estranhos, mas este código demonstra uma maneira de executar vários subprocessos usando asyncio e transmitir a saída.
fonte
wait()
diretamente está obsoletoExistem várias respostas aqui, mas nenhuma delas atendeu aos requisitos abaixo:
Não quero esperar o comando terminar ou poluir meu terminal com saídas de subprocesso.
Quero executar o script bash com redirecionamentos.
Quero oferecer suporte a tubulação em meu script bash (por exemplo
find ... | tar ...
).A única combinação que satisfaz os requisitos acima é:
fonte
Isso é abordado nos exemplos de subprocesso do Python 3 em "Aguarde o comando terminar de forma assíncrona":
O processo começará a ser executado assim que o
await asyncio.create_subprocess_exec(...)
for concluído. Se não tiver terminado no momento em que você ligarawait proc.communicate()
, ele aguardará para fornecer o status de saída. Se tiver terminado,proc.communicate()
vai voltar imediatamente.A essência aqui é semelhante à resposta de Terrel, mas acho que a resposta de Terrel parece complicar as coisas.
Veja
asyncio.create_subprocess_exec
para mais informações.fonte