matlib 에서 한글을 해결하기 위한 문제는 많으나.
WSL2 , Ubuntu 에서는 해결되지 않음
이에 GPT 와 대화 끝에 생성된 코드 첨부
# -*- coding: utf-8 -*-
"""
korean_font_wsl_test.py
WSL2(Ubuntu 22.04)에서 한글 깨짐 및 폰트 관련 이슈 점검/해결 올인원 스크립트
기능:
- 환경/인코딩 정보 출력
- 콘솔 출력 테스트
- UTF-8 파일 입출력 테스트
- Matplotlib: 안전 폰트 목록 적용(코딩 폰트 제외) + PNG/PDF 저장
- Pillow: 안전 폰트로 이미지 저장
폰트 우선순위(폴백 포함):
- NanumGothic → Noto Sans CJK KR → DejaVu Sans
- 'Coding' 이름의 폰트(예: NanumGothicCoding)는 제외
WSL 팁:
- WSL은 Windows 폰트를 자동 사용하지 않습니다.
- 반드시 WSL 내부에 폰트를 설치해야 합니다:
sudo apt install -y fonts-nanum fonts-noto-cjk fonts-dejavu-core
"""
import sys
import os
import platform
import locale
from pathlib import Path
from typing import Optional, List
import matplotlib
import matplotlib.pyplot as plt
from matplotlib import font_manager as fm
from PIL import Image, ImageDraw, ImageFont
# ===== 사용자 설정 =====
OUTPUT_DIR = Path("korean_font_test_output")
OUTPUT_DIR.mkdir(exist_ok=True)
# 테스트 텍스트
RAW_TEST_TEXT = "안녕하세요, 파이썬! 한글 테스트 — 숫자: 123, 기호: ±−×"
# 안전 모드: 유니코드 마이너스(−, U+2212)를 ASCII 하이픈(-)으로 치환
USE_SAFE_MINUS = True
TEST_TEXT = RAW_TEST_TEXT.replace("−", "-") if USE_SAFE_MINUS else RAW_TEST_TEXT
# 출력 파일
TEXT_FILE = OUTPUT_DIR / "hello_korean.txt"
PNG_FILE = OUTPUT_DIR / "matplotlib_korean.png"
PDF_FILE = OUTPUT_DIR / "matplotlib_korean.pdf"
PIL_PNG_FILE = OUTPUT_DIR / "pil_korean.png"
# 안전 폰트 이름(정확 이름 매칭; 순서=우선순위)
SAFE_FONT_NAMES = [
"NanumGothic", # 일반 나눔고딕 (Coding 제외)
"Noto Sans CJK KR", # 한글/다국어 지원 넓음
"DejaVu Sans", # 기호/수학 글리프 보강
]
# 'Coding' 폰트는 제외 (예: NanumGothicCoding)
EXCLUDE_KEYWORDS = ["coding"]
# ===== 유틸 =====
def is_wsl() -> bool:
rel = platform.release().lower()
return "microsoft" in rel or "wsl" in rel
def print_env_info():
print("=== 환경 정보 ===")
print(f"Python: {platform.python_version()} ({sys.executable})")
print(f"OS: {platform.system()} {platform.release()} ({platform.version()})")
print(f"WSL 감지: {is_wsl()}")
print(f"Matplotlib: {matplotlib.__version__}, Backend: {matplotlib.get_backend()}")
print(f"sys.stdout.encoding: {sys.stdout.encoding}")
try:
pref = locale.getpreferredencoding(False)
except Exception:
pref = "N/A"
print(f"locale.getpreferredencoding(False): {pref}")
print(f"FileSystemEncoding: {sys.getfilesystemencoding()}")
print("")
def try_fix_console_encoding():
enc = (sys.stdout.encoding or "").upper()
if "UTF-8" not in enc:
try:
sys.stdout.reconfigure(encoding="utf-8") # Py3.7+
print("[정보] sys.stdout 인코딩을 UTF-8로 재설정했습니다.")
except Exception as e:
print("[참고] 콘솔 인코딩 자동 재설정 실패:", repr(e))
print(" - VS Code/터미널이 UTF-8인지 확인")
print(" - PYTHONUTF8=1 환경변수 설정 권장\n")
def find_font_paths_by_exact_names(names: List[str]) -> List[str]:
"""정확한 폰트 이름 일치로 경로 수집, EXCLUDE_KEYWORDS 포함 시 제외"""
matched = []
for fe in fm.fontManager.ttflist:
name = (fe.name or "")
if any(k in name.lower() for k in EXCLUDE_KEYWORDS):
continue
if name in names and fe.fname and os.path.exists(fe.fname):
matched.append(fe.fname)
return matched
def setup_matplotlib_fonts_safe():
"""Matplotlib에 안전 폰트 목록 적용 + 폴백"""
# 축 라벨의 마이너스는 ASCII '-'로 강제 (tick 라벨 안전)
plt.rcParams["axes.unicode_minus"] = False
# (선택) PDF에서 14 core fonts 고정 사용 해제
plt.rcParams["pdf.use14corefonts"] = False
font_paths = find_font_paths_by_exact_names(SAFE_FONT_NAMES)
families = []
for path in font_paths:
fm.fontManager.addfont(path)
fam = fm.FontProperties(fname=path).get_name()
families.append(fam)
if families:
plt.rcParams["font.family"] = families # 리스트 설정 → 글리프 폴백 유도
print(f"[Matplotlib] 적용 폰트 목록: {families}")
else:
print("[경고] 안전 폰트를 찾지 못했습니다. 시스템 기본 폰트를 사용합니다.")
print(" - 설치 확인: sudo apt install -y fonts-nanum fonts-noto-cjk fonts-dejavu-core")
print(" - 캐시 초기화: rm -rf ~/.cache/matplotlib/*")
def test_console_output():
print("=== 콘솔 출력 테스트 ===")
print(TEST_TEXT)
print("-> 위 텍스트가 콘솔에 정상적으로 한글로 보이나요?\n")
def test_file_io():
print("=== 파일 입출력 테스트 (UTF-8) ===")
with open(TEXT_FILE, "w", encoding="utf-8") as f:
f.write(TEST_TEXT + "\n")
print(f"쓰기 완료: {TEXT_FILE}")
with open(TEXT_FILE, "r", encoding="utf-8") as f:
content = f.read().strip()
print("읽은 내용:", content)
print("-> 파일에 한글이 깨지지 않고 저장/읽기 되는지 확인하세요.\n")
def test_matplotlib_output():
print("=== Matplotlib 출력 테스트 ===")
fig, ax = plt.subplots(figsize=(8, 4), dpi=150)
ax.set_title("한글 폰트 테스트 (Matplotlib)")
ax.plot([1, 2, 3], [3, 1, 4], marker="o", label="데이터")
ax.legend()
ax.set_xlabel("가로축")
ax.set_ylabel("세로축")
ax.text(0.05, 0.80, TEST_TEXT, transform=ax.transAxes)
# RAW 텍스트 비교(옵션): 유니코드 마이너스를 그대로 넣어보는 라인
ax.text(0.05, 0.68, f"(RAW) {RAW_TEST_TEXT}", fontsize=9, color="dimgray",
transform=ax.transAxes)
fig.tight_layout()
fig.savefig(PNG_FILE)
fig.savefig(PDF_FILE)
plt.close(fig)
print(f"저장 완료: {PNG_FILE}, {PDF_FILE}")
print("-> 이미지/PDF에서 한글과 기호가 정상인지 확인하세요.\n")
def _choose_pillow_font_path() -> Optional[str]:
"""Pillow에서 사용할 트루타입 폰트 경로 선택 (안전 목록 우선)"""
# Matplotlib에서 찾은 경로 재사용
paths = find_font_paths_by_exact_names(SAFE_FONT_NAMES)
if paths:
return paths[0]
# 마지막 시도: font_manager의 어떤 폰트든 한 개(코딩 폰트 제외)
for fe in fm.fontManager.ttflist:
name = (fe.name or "")
if any(k in name.lower() for k in EXCLUDE_KEYWORDS):
continue
if fe.fname and os.path.exists(fe.fname):
return fe.fname
return None
def test_pillow_output():
print("=== Pillow 출력 테스트 ===")
img = Image.new("RGB", (1400, 420), color="white")
draw = ImageDraw.Draw(img)
font_path = _choose_pillow_font_path()
font = None
if font_path:
try:
font = ImageFont.truetype(font_path, size=48)
print(f"[Pillow] 적용 폰트: {font_path}")
except Exception as e:
print("[Pillow] truetype 로딩 실패:", repr(e))
if font is None:
font = ImageFont.load_default()
print("[Pillow] 한글 폰트를 찾지 못해 기본 폰트 사용 (한글/기호가 깨질 수 있음)")
draw.text((40, 40), "한글 폰트 테스트 (Pillow)", fill=(0, 0, 0), font=font)
draw.text((40, 130), TEST_TEXT, fill=(10, 50, 120), font=font)
draw.text((40, 220), f"(RAW) {RAW_TEST_TEXT}", fill=(80, 80, 80), font=font)
img.save(PIL_PNG_FILE)
print(f"저장 완료: {PIL_PNG_FILE}")
print("-> 이미지에서 한글과 기호가 정상인지 확인하세요.\n")
def main():
print_env_info()
try_fix_console_encoding()
test_console_output()
# Matplotlib: 안전 폰트 적용
setup_matplotlib_fonts_safe()
test_matplotlib_output()
# Pillow: 이미지 테스트
test_pillow_output()
# 파일 IO: UTF-8 테스트
test_file_io()
print("=== 테스트 완료 ===")
print(f"출력 폴더: {OUTPUT_DIR.resolve()}")
if is_wsl():
print("\n[WSL 안내]")
print("- WSL은 Windows 폰트를 자동으로 사용하지 않습니다.")
print("- 폰트 설치 권장: sudo apt install -y fonts-nanum fonts-noto-cjk fonts-dejavu-core")
print("- Matplotlib 캐시 초기화: rm -rf ~/.cache/matplotlib/*")
if __name__ == "__main__":
main()
% 보면은 잘못된 내용도 보이나 생성된 코드 그대로 첨부
'AI with 재미' 카테고리의 다른 글
| ubuntu 18.04 & gemini cli (0) | 2025.11.12 |
|---|---|
| Gemini Jules - 본인 스스로 답변 (0) | 2025.11.09 |
| 한경 매수 리포트 수집 (0) | 2025.11.04 |
| Naver news api 링크로 본문 가져오기 (0) | 2025.11.04 |
| copiliot 자기소개 (0) | 2025.11.02 |