Python에서 클래스간의 상호참조

고승우·2023년 5월 15일
0
post-thumbnail

PYQT5를 활용하여 작성한 A.py 파일과 일정 주기마다 메소드를 호출하는 B.py 파일간의 상호참조(circular import)가 문제가 되었다. 수직관계가 아닌 수평관계를 가진 두 클래스를 생성하려고 했고, 그 과정에서 B클래스에 A클래스의 인자를 포함시키고 A클래스의 메소드에서 B클래스의 메소드를 호출하다가 발생했다. 설계의 문제가 있음을 인지하고 import의 원리와 다양한 해결방법에 대해 포스트를 하려 한다.



상호참조(circular import란?)

두 개 이상의 파일에서 서로를 참조하여 만들어진 폐순환 때문에 발생한다.

실험삼아 같은 폴더에 위와 같은 코드를 넣고 실행시켜 보았다.

a.py

import b
def function_a():
    print('function_a')
    return b.function_b()
function_a()

b.py

import a
def function_b():
    print('function_b')
def function_c():
    print('function_c')
    return a.function_a()

오류가 나지 않고 정상적으로 실행이 된다. 이러한 상황을 이해하기 위해선 import, import time, run time에 대해 더 깊게 알아봐야 한다.



import란?

파이썬에서 import는 다른 파이썬 소스, 패키지 혹은 파이썬 라이브러리의 기능 전체 혹은 일부를 현재 프로그램 코드 문맥을 가져오는 일을 한다.


import의 동작방식

import를 활용해 다른 모듈을 반입하게 되면 파이썬 interpreter는 모듈이나 패키지 이름에 기반하여 해당 모듈의 이름으로 되어 있는 디렉토리나 파일을 찾아 해당 파일을 한 번 컴파일하여 바이트코드 모듈로 바꾼다. 이러한 과정은 해당 모듈의 파일을 퍼음부터 끝까지 읽어서 실행하는 것과 동일하다.


import time, runtime이란?

runtime이란 실제로 모든 코드가 실행되는 순간이다. 하지만 import time에서는 모듈에 들어 있는 코드를 위에서부터 순서대로 파싱하고 실행을 위한 바이트 코드를 생성한다. 이러한 결과물로 .pyc 파일이 생성된다(코드가 그대로 있을 경우 생략). Syntax Error 또한 코드를 파싱하는 과정에서 발생한다. 함수 본문, 클래스의 메소드 본문을 제외한 대부분의 코드가 import time에 실행한다.
즉, import time에 a.py의 function_a() 코드가 import time에 실행되어 a 듈과 b 모듈이 반복적으로 import 되어 오류가 발생한다고 한다.


해결 방법

import time에 순환 참조가 된다는 것이 문제라는 것을 알았다면, 모듈을 import 하는 시점을 runtime으로 옮겨 문제를 해결할 수 있다.

a.py

import b
def function_a():
    print('function_a')
    return b.function_b()
function_a()

b.py

def function_b():
    print('function_b')
def function_c():
    import a	# 함수 내에서 import
    print('function_c')
    return a.function_a()
profile
٩( ᐛ )و 

0개의 댓글