본문 바로가기

Python

[박혜웅] "cannot import name bar" in Python

python 은 정말 강력한 언어이지만, import 방식은 C와 비슷하게 매우 구식이다.

그래서 체계적으로 소스를 구성하지 않고 import를 남발하다보면, circular import 문제에 부딪히게 된다. 즉 순환하여 import 하는 경우 "cannot import name bar"와 같이 특정 모듈을 import 할 수 없어서 소스 실행이 되지 않는다.


우선 간략히 해결방법을 적으면,

1. 모듈을 구조적으로 설계하여, 상호 import하지 않도록 한다.

라이브러리성 모듈로 잘 분할해서 저장하고, 이 라이브러리성 모듈을 조합해서 실행하는 모듈은 소수만 유지하는 것이다.


2. from package import module 대신 import package.module을 사용한다.

from package import module 구문(statement)은 package가 생성(__init__.py호출)된 후에 사용할 수 있지만,  import package.module 구문은 바로 사용할 수 있기 때문이다. (아래 실행 결과 참조)


3. 도저히 해결할 수 없을만큼 import가 꼬인 경우, importlib.import_module('module', 'package') 를 사용한다.

import package.module 형태로도 이 에러가 해결되지 않는 경우가 있었는데, 꼬인 모듈들의 import문을 모두 importlib.import_module('module','package')로 치환해서 해결했다.



* from package import module의 실행 순서

# bage/test/__init__.py

print 'bage.test.__init__.py'


# bage/test/a.py

print 'a.py before "from bage.test import b"'

from bage.test import b

print 'a.py after "from bage.test import b"'

if __name__ == '__main__':

    pass


# bage/test/b.py

print 'b.py before "from bage.test import a"'

from bage.test import a

print 'b.py after "from bage.test import a"'


# 실행 결과 (raised circular import error)

# python a.py

a.py before "from bage.test import b"

bage.test.__init__.py

b.py before "from bage.test import a"

a.py before "from bage.test import b"

Traceback (most recent call last):

  File "C:\Users\bage\git\BageUtil2012.git\BageUtil2012\bage\test\a.py", line 8, in <module>

    from bage.test import b

  File "C:\Users\bage\git\BageUtil2012.git\BageUtil2012\bage\test\b.py", line 7, in <module>

    from bage.test import a

  File "C:\Users\bage\git\BageUtil2012.git\BageUtil2012\bage\test\a.py", line 8, in <module>

    from bage.test import b

ImportError: cannot import name b


* import package.module의 실행 순서

# bage/test/__init__.py

print 'bage.test.__init__.py'


# bage/test/a.py

print 'a.py before "import b"'

import b

print 'a.py after "import b"'

if __name__ == '__main__':

    pass


# bage/test/b.py

print 'b.py before "import b"'

import a

print 'b.py after "import b"'


# 실행 결과 (not raised circular import error)

# python a.py

a.py before "import b"

b.py before "import b"

a.py before "import b"

a.py after "import b"

b.py after "import b"

a.py after "import b"