본문 바로가기
코딩취미/Python

os.path.join에서 NoneType 오류가 발생하는 이유와 해결 방법

by 브링블링 2025. 5. 2.
반응형

📌 os.path.join에서 NoneType 오류가 발생하는 이유와 해결 방법

파이썬으로 경로를 조합할 때 가장 자주 쓰는 함수 중 하나인 os.path.join()은 간단하면서도 실수하기 쉬운 함수입니다.

특히 GUI 개발을 할 때 사용자의 입력이 누락되면 예상치 못한 NoneType 에러가 발생할 수 있습니다. 이 글에서는 os.path.join()에서 발생하는 TypeError의 원인을 살펴보고, 이를 방지하는 방법, pathlib으로의 대체, PySide6에서의 실용 예제까지 함께 소개합니다.


🧩 오류 상황 예시

TypeError: expected str, bytes or os.PathLike object, not NoneType
 

이 에러는 os.path.join()에 전달된 인자 중 None값이 포함되어 있을 때 발생합니다.
PySide6 같은 GUI 앱에서 경로를 만들다가 사용자가 값을 선택하지 않거나 입력하지 않으면 쉽게 발생할 수 있습니다.


✅ 1. 문제 코드 예시

import os

projectPath = os.path.join(self.ideDir, "Generation", self.audkVersion, "Example", "Build", "IAR", "TmplUserApp", self.ideVersion)
 

이 코드에서 self.ideDir, self.audkVersion, self.ideVersion 중 하나라도 None이면 에러가 발생합니다.


🛠 2. 해결 방법 요약

✔️ 값이 None이거나 빈 문자열인지 확인

def is_valid_path(value):
    return isinstance(value, str) and value.strip() != ""

✔️ 모든 값 검증 후 경로 생성

if all(is_valid_path(val) for val in [self.ideDir, self.audkVersion, self.ideVersion]):
    projectPath = os.path.join(
        self.ideDir, "Generation", self.audkVersion,
        "Example", "Build", "IAR", "TmplUserApp", self.ideVersion
    )
else:
    print("경로 구성 요소 중 유효하지 않은 값이 있습니다.")
반응형

💡 3. pathlib를 활용한 경로 조합 (추천)

os.path.join의 대안으로, Python 3.6 이상에서는 pathlib를 사용하면 코드가 더 읽기 쉽고 안전합니다.

from pathlib import Path

def build_project_path(ideDir, audkVersion, ideVersion):
    if all(is_valid_path(val) for val in [ideDir, audkVersion, ideVersion]):
        return Path(ideDir) / "Generation" / audkVersion / "Example" / "Build" / "IAR" / "TmplUserApp" / ideVersion
    return None
  • / 연산자로 경로를 직관적으로 연결할 수 있습니다.
  • Path 객체로 처리하면 플랫폼 호환성이 향상됩니다.

⚠️ 4. PySide6에서 오류 발생 시 팝업으로 경고 표시

PySide6 앱에서는 콘솔 대신 QMessageBox로 사용자에게 알려줄 수 있습니다.

from PySide6.QtWidgets import QMessageBox

def show_error(message):
    QMessageBox.critical(None, "오류", message)

🧪 5. PySide6 전체 예제 코드

import sys
from pathlib import Path
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout,
    QLineEdit, QPushButton, QMessageBox, QLabel
)

def is_valid_path(value):
    return isinstance(value, str) and value.strip() != ""

class PathExampleApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("경로 생성기")
        self.setMinimumWidth(400)

        self.ideDirInput = QLineEdit()
        self.audkVerInput = QLineEdit()
        self.ideVerInput = QLineEdit()
        self.resultLabel = QLabel()

        btn = QPushButton("경로 생성")
        btn.clicked.connect(self.create_path)

        layout = QVBoxLayout()
        layout.addWidget(QLabel("IDE 디렉토리:"))
        layout.addWidget(self.ideDirInput)
        layout.addWidget(QLabel("AUDK 버전:"))
        layout.addWidget(self.audkVerInput)
        layout.addWidget(QLabel("IDE 버전:"))
        layout.addWidget(self.ideVerInput)
        layout.addWidget(btn)
        layout.addWidget(QLabel("결과 경로:"))
        layout.addWidget(self.resultLabel)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

    def create_path(self):
        ideDir = self.ideDirInput.text()
        audkVer = self.audkVerInput.text()
        ideVer = self.ideVerInput.text()

        if all(is_valid_path(val) for val in [ideDir, audkVer, ideVer]):
            project_path = Path(ideDir) / "Generation" / audkVer / "Example" / "Build" / "IAR" / "TmplUserApp" / ideVer
            self.resultLabel.setText(str(project_path))
        else:
            QMessageBox.critical(self, "입력 오류", "모든 필드를 올바르게 입력해주세요.")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = PathExampleApp()
    win.show()
    sys.exit(app.exec())

✅ 마무리

  • os.path.join()은 모든 인자가 문자열이어야 하며, None이나 ""이면 오류가 발생합니다.
  • pathlib를 사용하면 더 안전하고 직관적인 코드 작성이 가능합니다.
  • PySide6에서는 사용자 입력이 잘못되었을 때 QMessageBox를 활용해 안내 메시지를 보여줄 수 있습니다.
  • GUI 앱에서는 항상 사용자 입력을 검증하고, 예외 상황에 대비한 방어 코딩이 중요합니다.
반응형