Como iniciar um processo de fundo em Python?
estou a tentar adicionar um programa de shell à versão python muito mais legível. O script de shell original inicia vários processos (utilitários, monitores, etc.) in the background with"&". Como posso conseguir o mesmo efeito em python? Gostaria que estes processos não morressem quando os scripts python terminarem. Tenho a certeza que está relacionado com o conceito de um demónio de alguma forma, mas não consegui descobrir como fazer isto facilmente.
6 answers
Nota : Esta resposta é menos actual do que era quando publicada em 2009. A utilização do módulo subprocess
mostrado noutras respostas é agora recomendada nos documentos
(Note - se que o módulo de subprocessamento oferece facilidades mais poderosas para reproduzir novos processos e obter os seus resultados; a utilização desse módulo é preferível à utilização destas funções.)
Se quiser que o seu processo comece em segundo plano, pode usar system()
e chamá-lo em da mesma forma que o seu script shell, ou você pode spawn
:
import os
os.spawnl(os.P_DETACH, 'some_long_running_command')
(ou, em alternativa, pode tentar a bandeira menos portátil os.P_NOWAIT
).
Ver a documentação aqui.
Enquanto a solução de jkp funciona, a maneira mais nova de fazer as coisas (e a forma como a documentação recomenda) é usar o módulo subprocess
. Para comandos simples seu equivalente, mas oferece mais opções se você quiser fazer algo complicado.
Exemplo para o seu caso:
import subprocess
subprocess.Popen(["rm","-r","some.file"])
Isto deve ser executado rm -r somefile
em segundo plano. mas tenha cuidado: {[4] } só executa um processo em segundo plano se nada no programa python depender do resultado do comando ser executar:
Por exemplo, o seguinte comando irá Não correr em segundo plano:
import subprocess
ls_output=subprocess.Popen(["ls", "-a"], stdout=subprocess.PIPE)
Veja a documentação aqui.
Também, um ponto de clarificação:" fundo " puramente um conceito de concha: o que você provavelmente quer é desovar um novo processo. Eu usei "background" aqui para se referir ao comportamento shell-background-like, mas não confunda isso com o processo realmente estar no fundo.
Você provavelmente quer a resposta para "Como chamar um comando externo em Python".
A abordagem mais simples é usar a função os.system
, por exemplo:
import os
os.system("some_command &")
Basicamente, o que quer que passe para a função system
será executado da mesma forma que se o tivesse passado para a shell num script.
No windows (win xp), o processo pai não terminará até que o longtask.py
termine o seu trabalho. Não é o que você quer no script CGI. O problema não é específico para Python, na comunidade PHP os problemas são os mesmos.
A solução passa DETACHED_PROCESS
process Creation Flag para a função CreateProcess
subjacente na API win. Se por acaso tiver instalado o pywin32, poderá importar a bandeira do módulo win32process, caso contrário poderá deve defini-lo você mesmo:
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
Usar subprocess.Popen()
com o parâmetro close_fds=True
, o que permitirá que o subprocessamento gerado seja separado do próprio processo Python e continue a correr mesmo após as saídas do Python.
Https://gist.github.com/yinjimmy/d6ad0742d03d54518e9f
import os, time, sys, subprocess
if len(sys.argv) == 2:
time.sleep(5)
print 'track end'
if sys.platform == 'darwin':
subprocess.Popen(['say', 'hello'])
else:
print 'main begin'
subprocess.Popen(['python', os.path.realpath(__file__), '0'], close_fds=True)
print 'main end'
Provavelmente quer começar a investigar o módulo de SO para procurar diferentes tópicos (abrindo uma sessão interactiva e emitindo ajuda(os)). As funções relevantes são fork e qualquer uma das exec. Para lhe dar uma ideia de como começar, coloque algo assim numa função que executa o fork (a função precisa de ter uma lista ou tupla 'args' como um argumento que contém o nome do programa e os seus parâmetros; Você também pode querer definir stdin, out e err para o novo fio):
try:
pid = os.fork()
except OSError, e:
## some debug output
sys.exit(1)
if pid == 0:
## eventually use os.putenv(..) to set environment variables
## os.execv strips of args[0] for the arguments
os.execv(args[0], args)