IT_Server/modules/backup/iop_server.py

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()