<질문>
쉘 스크립트를 훨씬 더 읽기 쉬운 파이썬 버전으로 포팅하려고 합니다. 원래 셸 스크립트는 "&"를 사용하여 백그라운드에서 여러 프로세스(유틸리티, 모니터 등)를 시작합니다. 파이썬에서 어떻게 동일한 효과를 얻을 수 있습니까? 파이썬 스크립트가 완료될 때 이러한 프로세스가 죽지 않기를 바랍니다. 왠지 데몬의 개념과 관련이 있는 것 같은데 쉽게 할 수 있는 방법을 찾지 못했습니다.
<답변1>
하는 동안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
설명서를 참조하십시오here.
또한 설명의 요점: 여기에서 사용하는 "배경"은 순전히 쉘 개념입니다. 기술적으로 의미하는 것은 프로세스가 완료될 때까지 기다리는 동안 차단하지 않고 프로세스를 생성하려는 것입니다. 그러나 여기서는 "백그라운드"를 사용하여 쉘 백그라운드와 같은 동작을 나타냅니다.
<답변2>
메모: 이 답변은 2009년에 게시된 것보다 최신 정보가 아닙니다.subprocess
다른 답변에 표시된 모듈이 이제 권장됩니다.in the docs
(subprocess 모듈은 새 프로세스를 생성하고 그 결과를 검색하기 위한 보다 강력한 기능을 제공합니다. 이 기능을 사용하는 것보다 해당 모듈을 사용하는 것이 좋습니다.)
백그라운드에서 프로세스를 시작하려면 다음 중 하나를 사용할 수 있습니다.system()
쉘 스크립트와 같은 방식으로 호출하거나 다음을 수행할 수 있습니다.spawn
그것:
import os
os.spawnl(os.P_DETACH, 'some_long_running_command')
(또는 대안으로 휴대성이 떨어지는os.P_NOWAIT
깃발).
<답변3>
당신은 아마도 대답을 원할 것입니다"How to call an external command in Python".
가장 간단한 방법은 다음을 사용하는 것입니다.os.system
기능, 예:
import os
os.system("some_command &")
기본적으로, 당신이system
함수는 스크립트에서 쉘에 전달한 것과 동일하게 실행됩니다.
<답변4>
나는 이것을 찾았다here:
Windows(win xp)에서 상위 프로세스는 종료될 때까지 완료되지 않습니다.longtask.py
작업을 마쳤습니다. CGI 스크립트에서 원하는 것이 아닙니다. 문제는 Python에만 국한되지 않으며 PHP 커뮤니티에서도 문제는 동일합니다.
해결책은 합격이다DETACHED_PROCESS
Process Creation Flag기본으로CreateProcess
승리 API의 기능. pywin32를 설치한 경우 win32process 모듈에서 플래그를 가져올 수 있습니다. 그렇지 않으면 직접 정의해야 합니다.
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
<답변5>
사용subprocess.Popen()
이랑close_fds=True
생성된 하위 프로세스가 Python 프로세스 자체에서 분리되고 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'
<답변6>
출력을 캡처하고 threading
을 사용하여 백그라운드에서 실행
말한 바와 같이on this answer, 다음을 사용하여 출력을 캡처하는 경우stdout=
그런 다음read()
, 프로세스가 차단됩니다.
그러나 이것이 필요한 경우가 있습니다. 예를 들어 시작하고 싶었습니다.two processes that talk over a port between them, stdout을 로그 파일 및 stdout에 저장합니다.
그만큼threading
module그렇게 할 수 있습니다.
먼저 이 질문에서 출력 리디렉션 부분만 수행하는 방법을 살펴보십시오.Python Popen: Write to stdout AND log file simultaneously
그 다음에:
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에서 테스트되었습니다.
<답변7>
대화형 세션을 열고 help(os)를 발행하여) 다른 스레드를 분기하기 위한 os 모듈 조사를 시작하고 싶을 것입니다. 관련 기능은 fork 및 exec 기능입니다. 시작하는 방법에 대한 아이디어를 제공하려면 포크를 수행하는 함수에 다음과 같은 것을 넣으십시오(함수는 프로그램의 이름과 해당 매개 변수를 포함하는 인수로 목록 또는 튜플 '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)
<답변8>
당신이 사용할 수있는
import os
pid = os.fork()
if pid == 0:
Continue to other code ...
이렇게 하면 Python 프로세스가 백그라운드에서 실행됩니다.
<답변9>
나는 이것을 아직 시도하지 않았지만 .py 파일 대신 .pyw 파일을 사용하면 도움이 될 것입니다. pyw 파일에는 콘솔이 없으므로 이론적으로 백그라운드 프로세스처럼 표시되거나 작동하지 않아야 합니다.
'개발 > Python' 카테고리의 다른 글
[파이썬] pandas 다른 데이터 프레임에 없는 행을 가져오는 방법은? (0) | 2023.01.20 |
---|---|
[파이썬] Pylint 경고를 비활성화는 방법은? (0) | 2023.01.20 |
[파이썬] UnicodeDecodeError: 'utf8' codec can't decode byte 0x9c (0) | 2023.01.20 |
[파이썬] git 저장소 안에 virtualenv 디렉터리가 있는 것이 나쁜가요? (0) | 2023.01.20 |