92 lines
4.1 KiB
Python
92 lines
4.1 KiB
Python
import subprocess
|
|
import logging
|
|
import socket
|
|
import random
|
|
import time
|
|
import os
|
|
import sys
|
|
|
|
class IOPaint_Server:
|
|
def __init__(self, logger, base_dir):
|
|
self.logger = logger
|
|
self.base_dir = base_dir
|
|
|
|
def find_free_port(self, port_range=(7322, 7322)):
|
|
"""포트 범위 내에서 사용 가능한 포트 반환"""
|
|
for _ in range(20):
|
|
port = random.randint(*port_range)
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
try:
|
|
s.bind(("0.0.0.0", port))
|
|
return port
|
|
except OSError:
|
|
continue
|
|
raise RuntimeError("사용 가능한 포트를 찾을 수 없습니다.")
|
|
|
|
def start(self, wait_ready=30):
|
|
"""iopaint 서버를 실행하고, 정상 실행시 포트 반환"""
|
|
port = self.find_free_port()
|
|
model_dir = os.path.join(self.base_dir, 'modules', 'iop', 'models')
|
|
cmd = [sys.executable, '-m', 'iopaint', 'start', '--model=migan', '--device=cpu', '--port', str(port), '--model-dir', model_dir]
|
|
self.logger.log(f"[IOPaint] 실행 환경 파이썬: {sys.executable}", level=logging.INFO)
|
|
self.logger.log(f"[IOPaint] 실행 명령: {' '.join(cmd)}", level=logging.INFO)
|
|
self.logger.log(f"[IOPaint] 모델 디렉토리: {model_dir}", level=logging.INFO)
|
|
# pip list로 iopaint 설치여부 확인
|
|
try:
|
|
pip_list = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], text=True)
|
|
found = any('iopaint' in line for line in pip_list.splitlines())
|
|
if found:
|
|
self.logger.log("[IOPaint] iopaint 모듈이 현재 환경에 설치되어 있습니다.", level=logging.INFO)
|
|
else:
|
|
self.logger.log("[IOPaint] iopaint 모듈이 현재 환경에 설치되어 있지 않습니다!", level=logging.WARNING)
|
|
except Exception as e:
|
|
self.logger.log(f"[IOPaint] pip list 실행 실패: {e}", level=logging.ERROR, exc_info=True)
|
|
|
|
# subprocess를 실시간 출력으로 실행
|
|
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1)
|
|
self.logger.log(f"[IOPaint] 서버 준비 확인 시작 (최대 {wait_ready}초 대기)", level=logging.INFO)
|
|
url = f"http://localhost:{port}/api/v1/server-config"
|
|
start_time = time.time()
|
|
stdout_lines = []
|
|
stderr_lines = []
|
|
import threading
|
|
def read_stream(stream, lines, stream_name):
|
|
for line in iter(stream.readline, ''):
|
|
lines.append(line)
|
|
print(f"[{stream_name}] {line}", end='')
|
|
stream.close()
|
|
t_out = threading.Thread(target=read_stream, args=(proc.stdout, stdout_lines, 'STDOUT'))
|
|
t_err = threading.Thread(target=read_stream, args=(proc.stderr, stderr_lines, 'STDERR'))
|
|
t_out.start()
|
|
t_err.start()
|
|
ready = False
|
|
while time.time() - start_time < wait_ready:
|
|
try:
|
|
import requests
|
|
r = requests.get(url, timeout=2)
|
|
if r.status_code == 200:
|
|
self.logger.log(f"[IOPaint] 서버가 포트 {port}에서 준비됨.")
|
|
ready = True
|
|
break
|
|
except Exception as e:
|
|
time.sleep(0.5)
|
|
t_out.join(timeout=2)
|
|
t_err.join(timeout=2)
|
|
if ready:
|
|
return port
|
|
# 실패 시 로그 및 예외
|
|
self.logger.log(f"[IOPaint] 서버 실행 실패.\nstdout:\n{''.join(stdout_lines)}\nstderr:\n{''.join(stderr_lines)}", level=logging.ERROR, exc_info=True)
|
|
print("[IOPaint] 서버 실행 실패. 전체 STDOUT:")
|
|
print(''.join(stdout_lines))
|
|
print("[IOPaint] 서버 실행 실패. 전체 STDERR:")
|
|
print(''.join(stderr_lines))
|
|
raise RuntimeError(f"IOPaint 서버가 {wait_ready}초 내에 준비되지 않았습니다.")
|
|
|
|
# if __name__ == "__main__":
|
|
# logging.basicConfig(level=logging.INFO)
|
|
# logger = logging.getLogger(__name__)
|
|
# base_dir = os.path.dirname(os.path.abspath(__file__))
|
|
# iop = IOPaint(logger, base_dir)
|
|
# iop.start()
|
|
|