"""fix_bpy_import.py — scanvas_maker.py 의 bpy import 오류 핫픽스. 증상: [모듈 없음] Blender 렌더 모듈을 찾을 수 없습니다: No module named 'bpy' 원인: apply_blender_patch.py v1 의 P1 콜백 안에서 dump_params_to_json 을 gate_3d_builder_bpy 에서 import 하도록 되어 있는데, 이 모듈은 첫 줄에 `import bpy` 가 있어 S-CANVAS conda env(GUI 측)에서는 import 불가. 수정: 동일 함수의 bpy-무의존 버전인 params_to_json.dump_dataclass_to_json 으로 교체. (params_to_json.py 는 이미 D:\\에 있음) 이 스크립트는 idempotent: 이미 수정돼있으면 변경 없음. 백업: 실행 전 scanvas_maker.py.bak_bpyfix 자동 생성. 사용법: cd D:\\2026\\PROGRAM\\1_S-CANVAS python fix_bpy_import.py """ from __future__ import annotations import ast import shutil import sys from pathlib import Path TARGET = Path("scanvas_maker.py") BACKUP = Path("scanvas_maker.py.bak_bpyfix") # 정확한 한 줄을 교체 (CRLF/LF 무관 — bytes로 처리) OLD_LINE = b"from gate_3d_builder_bpy import dump_params_to_json as _dump_gate" NEW_LINE = b"from params_to_json import dump_dataclass_to_json as _dump_gate" def main(): if not TARGET.is_file(): sys.exit(f"[ERR] {TARGET} 가 현재 폴더에 없습니다. " f"D:\\2026\\PROGRAM\\1_S-CANVAS 에서 실행하세요.") raw = TARGET.read_bytes() print(f"파일: {TARGET} ({len(raw):,} bytes)") if NEW_LINE in raw: print("\n→ 이미 수정됨. 추가 작업 없음.") # 그래도 import 실제로 동작하는지 확인 if not Path("params_to_json.py").is_file(): print("\n ⚠ 경고: params_to_json.py 가 현재 폴더에 없습니다.") print(" S-CANVAS 폴더에 이 모듈이 있어야 import 가 성공합니다.") return 0 if OLD_LINE not in raw: print("\n[INFO] OLD 패턴을 찾지 못했습니다.") print(" apply_blender_patch.py 를 먼저 실행했는지 확인하세요.") # 진단 — 어떤 import가 있는지 for keyword in [b"gate_3d_builder_bpy", b"_dump_gate", b"dump_params_to_json"]: n = raw.count(keyword) print(f" '{keyword.decode()}' 발생: {n}회") sys.exit(1) # params_to_json.py 가 실제로 있는지 미리 확인 if not Path("params_to_json.py").is_file(): sys.exit("[ERR] params_to_json.py 가 현재 폴더에 없습니다. " "이 모듈이 import 대상입니다.") # 단일 라인 치환 new_raw = raw.replace(OLD_LINE, NEW_LINE, 1) n_replaced = raw.count(OLD_LINE) - new_raw.count(OLD_LINE) print(f" 교체 라인 수: {n_replaced}") # AST parse 검증 (utf-8 디코드 후) try: text = new_raw.decode("utf-8") # CRLF면 그대로, AST는 양쪽 다 받음 ast.parse(text) print(f" AST parse: OK ({len(text.splitlines()):,} lines)") except SyntaxError as e: sys.exit(f"\n[ERR] 수정 후 syntax error: {e}\n파일 변경 안 함.") # 백업 shutil.copy2(TARGET, BACKUP) print(f"\n 백업: {BACKUP}") # 저장 TARGET.write_bytes(new_raw) print(f"\n✓ 핫픽스 적용 완료: {TARGET} ({len(new_raw):,} bytes)") print("\n변경 내용:") print(f" - {OLD_LINE.decode()}") print(f" + {NEW_LINE.decode()}") print("\n다음 단계:") print(" 1) S-CANVAS 재시작 (또는 그냥 다이얼로그를 다시 열어 다시 시도)") print(" 2) '🎨 Blender 렌더' 버튼 클릭") if __name__ == "__main__": sys.exit(main() or 0)