쉘 스크립트를 훨씬 더 읽기 쉬운 파이썬 버전으로 이식하려고합니다. 원래 쉘 스크립트는 “&”로 백그라운드에서 여러 프로세스 (유틸리티, 모니터 등)를 시작합니다. 파이썬에서 어떻게 동일한 효과를 얻을 수 있습니까? 파이썬 스크립트가 완료 될 때 이러한 프로세스가 죽지 않기를 바랍니다. 나는 그것이 어떻게 든 데몬의 개념과 관련이 있다고 확신하지만, 이것을 쉽게하는 방법을 찾을 수 없었습니다.
답변
참고 :이 답변은 2009 년에 게시 된 것보다 최신 정보입니다. subprocess
이제 다른 답변에 표시된 모듈을 사용하는 것이 문서에서 권장 됩니다.
(하위 프로세스 모듈은 새로운 프로세스를 생성하고 결과를 검색 할 수있는보다 강력한 기능을 제공합니다.이 기능을 사용하는 것보다 해당 모듈을 사용하는 것이 좋습니다.)
프로세스를 백그라운드에서 시작하려면 system()
셸 스크립트와 동일한 방식으로 프로세스를 사용 하거나 호출하거나 다음과 같이 할 수 spawn
있습니다.
import os
os.spawnl(os.P_DETACH, 'some_long_running_command')
(또는 대안으로 이식성이 낮은 os.P_NOWAIT
플래그를 사용해보십시오 ).
답변
jkp 의 솔루션이 작동 하는 동안 최신 방식으로 작업을 수행하고 문서가 권장하는 방식으로 subprocess
모듈 을 사용하는 것 입니다. 간단한 명령의 경우에는 동일하지만 복잡한 작업을 수행하려는 경우 더 많은 옵션을 제공합니다.
귀하의 경우에 대한 예 :
import subprocess
subprocess.Popen(["rm","-r","some.file"])
rm -r some.file
백그라운드에서 실행 됩니다. .communicate()
에서 반환 된 객체 를 호출 Popen
하면 완료 될 때까지 차단되므로 백그라운드에서 실행하려면 수행하지 마십시오.
import subprocess
ls_output=subprocess.Popen(["sleep", "30"])
ls_output.communicate() # Will block for 30 seconds
또한 설명의 요점 : 여기서 사용하는 “배경”은 순전히 쉘 개념입니다. 기술적으로, 의미는 프로세스가 완료되기를 기다리는 동안 차단하지 않고 프로세스를 생성하려고한다는 것입니다. 그러나 여기서는 “배경”을 사용하여 셸 배경과 유사한 동작을 나타냅니다.
답변
“Python에서 외부 명령을 호출하는 방법”에 대한 답변을 원할 것입니다 .
가장 간단한 방법은 os.system
다음과 같은 기능 을 사용하는 것입니다.
import os
os.system("some_command &")
기본적으로 system
함수에 전달하는 것은 스크립트의 쉘에 전달한 것과 동일하게 실행됩니다.
답변
Windows (win xp)에서 부모 프로세스는 작업이 완료 될 때까지 완료되지 않습니다 longtask.py
. CGI 스크립트에서 원하는 것이 아닙니다. 이 문제는 Python에만 국한된 것은 아니며 PHP 커뮤니티에서는 문제가 동일합니다.
해결책은 DETACHED_PROCESS
프로세스 생성 플래그 를 CreateProcess
win API 의 기본 함수 로 전달 하는 것입니다. pywin32를 설치 한 경우 win32process 모듈에서 플래그를 가져올 수 있습니다. 그렇지 않으면 직접 정의해야합니다.
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
답변
생성 된 하위 프로세스를 Python 프로세스 자체에서 분리하고 Python이 종료 된 후에도 계속 실행되도록 subprocess.Popen()
하는 close_fds=True
매개 변수 와 함께 사용하십시오 .
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'
답변
대화식 세션을 열고 도움말을 발행하여 다른 스레드를 포크하기 위해 os 모듈 조사를 시작하고 싶을 것입니다. 관련 기능은 포크 및 모든 실행 기능입니다. 시작하는 방법에 대한 아이디어를 얻으려면 포크를 수행하는 함수에 이와 같은 것을 넣으십시오 (함수는 프로그램의 이름과 매개 변수를 포함하는 인수로 목록 또는 튜플 ‘args’를 가져와야합니다. 새 스레드에 대한 stdin, out 및 err 정의) :
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)
답변
캡처 출력 및 백그라운드에서 실행 threading
이 답변 에서 언급했듯이 출력을 캡처 stdout=
한 다음 시도 read()
하면 프로세스가 차단됩니다.
그러나 이것이 필요한 경우가 있습니다. 예를 들어, 두 포트 사이에서 통신하는 두 개의 프로세스 를 시작 하고 stdout을 로그 파일과 stdout에 저장하려고했습니다.
threading
모듈은 우리가 그렇게 할 수 있습니다.
먼저이 질문에서 출력 리디렉션 부분을 단독으로 수행하는 방법을 살펴보십시오 .Python Popen : stdout 및 log 파일에 동시에 쓰기
그때:
main.py
#!/usr/bin/env python3
import os
import subprocess
import sys
import threading
def output_reader(proc, file):
while True:
byte = proc.stdout.read(1)
if byte:
sys.stdout.buffer.write(byte)
sys.stdout.flush()
file.buffer.write(byte)
else:
break
with subprocess.Popen(['./sleep.py', '0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc1, \
subprocess.Popen(['./sleep.py', '10'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc2, \
open('log1.log', 'w') as file1, \
open('log2.log', 'w') as file2:
t1 = threading.Thread(target=output_reader, args=(proc1, file1))
t2 = threading.Thread(target=output_reader, args=(proc2, file2))
t1.start()
t2.start()
t1.join()
t2.join()
sleep.py
#!/usr/bin/env python3
import sys
import time
for i in range(4):
print(i + int(sys.argv[1]))
sys.stdout.flush()
time.sleep(0.5)
실행 후 :
./main.py
stdout은 두 줄마다 다음을 포함하기 위해 0.5 초마다 업데이트됩니다.
0
10
1
11
2
12
3
13
각 로그 파일에는 지정된 프로세스에 대한 해당 로그가 포함됩니다.
고무시키는 : https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/
Ubuntu 18.04, Python 3.6.7에서 테스트되었습니다.