본문 바로가기

개발

[TIL] 파이썬 typing 모듈을 사용할 때 Import Error가 나는 경우

반응형

파이썬에서 typing 모듈을 사용할 때, circular import 이슈가 발생할 때가 있다.

예를 들어서

    # core/alphabets.py
    from .character import Character

    class Alphabets():
        def __init__(self):
            self.alphabet_list = []

        def add_alphabet(self, character: Character):
            self.alphabet_list.append(character)

        def remove_character(self, char: str):
            for i in range(len(self.alphabet_list)):
                if self.alphabet_list[i].char == char:
                    del self.alphabet_list[i]
# core/character.py
from .alphabets import Alphabets


class Character():
    def __init__(self, char: str):
        self.char = char

    def remove_from_alphabet(self, alphabets: Alphabets):
        alphabets.remove_character(self.char)
# core/__init__.py
from .alphabets import Alphabets
from .character import Character
# __main__.py
from core import Alphabets, Character

if __name__ == "__main__":
    alphabets = Alphabets()
    a = Character('a')
    alphabets.add_alphabet(a)
    print(alphabets.alphabet_list)
    a.remove_from_alphabet(alphabets)
    print(alphabets.alphabet_list)

위의 경우 circular import이슈가 발생한다. core/alphabets.py에서도 character.py를 임포트하려하고 character.py에서도 alphabets.py를 순환참조 문제가 생기면서, ImportError가 발생한다.

이런 경우 typing 모듈의 TYPE_CHECKING 을 확인해주면 된다. 그리고 각 클래스 타입은 문자열로 적어준다.

# core/alphabets.py
from typing import TYPE_CHECKING

# 오로지 타입체킹시에만
if TYPE_CHECKING:
    from .character import Character


class Alphabets():
    def __init__(self):
        self.alphabet_list = []

    # Character를 String으로 Typing
    def add_alphabet(self, character: 'Character'):
        self.alphabet_list.append(character)

    def remove_character(self, char: str):
        for i in range(len(self.alphabet_list)):
            if self.alphabet_list[i].char == char:
                del self.alphabet_list[i]
# core/character.py
from .alphabets import Alphabets


class Character():
    def __init__(self, char: str):
        self.char = char

    def remove_from_alphabet(self, alphabets: Alphabets):
        alphabets.remove_character(self.char)
# core/__init__.py
from .alphabets import Alphabets
from .character import Character
# __main__.py
from core import Alphabets, Character

if __name__ == "__main__":
    alphabets = Alphabets()
    a = Character('a')
    alphabets.add_alphabet(a)
    print(alphabets.alphabet_list)
    a.remove_from_alphabet(alphabets)
    print(alphabets.alphabet_list)

실행하면 문제없이 잘 실행된다.

[<core.character.Character object at 0x000001CB2B923240>]
[]
반응형