차밍이

[Python] 패키지 구성을 위해 __init__ 파일과 __all__에 대해 알아보자 본문

파이썬/기본 문법 정리

[Python] 패키지 구성을 위해 __init__ 파일과 __all__에 대해 알아보자

2022. 6. 6. 13:51
반응형

목차

    1. example package shapes 구조

    __init____all__를 알기 위해서 예시로 사용할 package shapes의 구조와 코드를 먼저 보고가자.

    tree

    shapes/
        __init__.py
        area.py
        volume.py

    shapes/area.py

    PI = 3.14
    
    # 원의 면적을 구해 주는 함수
    def circle(radius):
        return PI * radius * radius
    
    # 정사각형의 면적을 구해 주는 함수
    def square(length):
        return length * length

    shapes/volume.py

    PI = 3.14
    
    # 구의 부피를 구해 주는 함수
    def sphere(radius):
        return (4/3) * PI * radius * radius * radius
    
    # 정육면체의 부피를 구해 주는 함수
    def cube(length):
        return length * length * length

     

    2. __init__ 파일이란?

    패키지 안에는 __init__.py라는 파일이 있습니다.

    __init__.py 파일 (지금부터는 그냥 init 파일이라고 하겠습니다) 은 '이 폴더는 파이썬 패키지다'라고 말해 주는 파일입니다.

    파이썬 3.3 이전 버전에서는 init 파일이 필수였습니다.

    파이썬 3.3 이후 버전부터는 init 파일이 필수가 아니게 됐지만 파이썬 하위 버전과의 호환성과 패키지의 명확성을 위해 항상 패키지 안에 init 파일을 만들어 주는 것을 권장 드립니다.

    처음으로 패키지나 패키지 안에 있는 어떤 것을 임포트하면 가장 먼저 패키지의 init 파일에 있는 코드가 실행됩니다.

     

    3. __init__ 파일 활용하기

    init 파일을 어떻게 활용하는지 정리해 봅시다.

    3-1. __init__ 파일에서 임포트 사용하기

    패키지를 임포트하면 기본적으로 패키지 안에 있는 내용은 임포트되지 않습니다. 패키지를 임포트할 때 패키지 안에 있는 내용도 함께 임포트하고 싶다면 init 파일을 활용해야 합니다.

    init 파일에 패키지와 함께 임포트하고 싶은 것들을 써 주면 됩니다.

    shapes/__init__.py

    from shapes import area, volume

    그러면 이제 shapes 패키지를 임포트하면 areavolume 모듈도 임포트되겠죠? init 파일에서 임포트하는 것은 패키지 안으로 임포트된다고 생각하시면 됩니다. areavolume 모듈은 아래와 같이 접근할 수 있습니다.

    run.py

    import shapes
    
    print(shapes.area.circle(2))
    print(shapes.volume.sphere(2))

    그리고 모듈 대신 모듈의 함수들을 직접 임포트할 수도 있습니다.

    shapes/__init__.py

    from shapes.area import circle, square

    그러면 우리는 이 함수들을 아래와 같이 접근할 수 있습니다.

    run.py

    import shapes
    
    print(shapes.circle(2))
    print(shapes.square(3))

    shapes 패키지 안에서 함수들을 직접 가져왔기 때문에 area를 건너뛸 수 있는 거죠. init 파일에서 임포트되는 것은 항상 package.으로 접근할 수 있습니다. 위 처럼 호출 방식을 바꿔주는 것은 유용하게 쓰일 때도 있습니다.

     

    3-2. __init__ 파일에서 변수 정의하기

    상수값 PIarea 모듈에서도 쓰이고 volume 모듈에서도 쓰입니다. PI처럼 패키지에 있는 여러 모듈이 필요로 하는 것들은 각 모듈에서 정의하지 않고 패키지 안에서 한 번만 정의해 주는 게 좋습니다. 똑같은 걸 여러 번 정의하는 건 비효율적이고 실수로 하나를 잘 못 정의하면 프로그램에 오류가 나기 때문입니다.

    PI를 패키지 안에서 한 번만 정의해 주려면 (즉 패키지 레벨에서 정의해 주려면) PIshapes 패키지의 init 파일에서 정의해 주면 됩니다.

    shapes/__init__.py

    PI = 3.14

    그리고 패키지 안에 있는 모듈에서는 PI를 임포트하면 됩니다.

    shapes/area.py

    from shapes import PI
    
    # 원의 면적을 구해 주는 함수
    def circle(radius):
            ...

    shapes/volume.py

    from shapes import PI
    
    # 구의 부피를 구해 주는 함수
    def sphere(radius):
        ...

    PI같은 상수뿐만이 아니라 여러 모듈에서 필요한 변수, 함수 또는 객체는 패키지의 init 파일에서 정의해 주는 게 좋습니다.

    그리고 패키지의 init 파일에서 정의되는 것들은 패키지 밖에서도 사용할 수 있습니다.

    run.py

    # PI 직접 임포트
    from shapes import PI
    
    # 패키지 임포트 후 shapes. 으로 접근
    import shapes
    shapes.PI

     

    4. __all__ 특수 변수란?

    __all__ 특수 변수는 우리가 import \*를 했을 때 임포트 대상에서 어떤 것들을 가져와야 하는지를 정해 주는 변수입니다. 임포트 대상에서 내용 전체를 가져오라고 했을 때 '전체'가 무엇인지 정의해 주는 거죠. __all__ 은 모듈에도 적용되고 패키지에도 적용됩니다.

     

    5. __all__ 변수 활용하기

    5-1. import *

    모듈을 임포트할 때 from <module> import *를 하면 모듈의 모든 내용이 임포트됩니다.

    하지만 모듈 대신 패키지에 from <package> import *를 하면 패키지 안에 있는 게 아무것도 임포트되지 않습니다.

     

    5-2. __all__ 과 모듈

    모듈의 __all__ 은 모듈에 해당하는 파일에서 정의합니다. 예를 들어 area.py에 아래와 같은 코드를 추가해 주면:

    shapes/area.py

    # __all__ 정의
    __all__ = ['circle', 'square'] 
    
    PI = 3.14
    
    # 원의 면적을 구해 주는 함수
    def circle(radius):
        return PI * radius * radius  
    
    # 정사각형의 면적을 구해 주는 함수
    def square(length):
        return length * length

    from shapes.area import *를 했을 때 area 모듈의 모든 내용이 임포트되지 않고 circlesquare 함수만 임포트됩니다.

     

    5-3. __all__ 과 패키지

    패키지의 __all__ 은 패키지에 해당하는 init 파일에서 정의합니다. 예를 들어 shapes 패키지의 init 파일에 아래와 같은 코드를 추가해 주면:

    shapes/__init__.py

    # __all__ 정의
    __all__ = ['area', 'volume']

    이제 from shapes import *를 하면 area 모듈과 volume 모듈이 임포트됩니다.

    __all__을 사용하면 패키지나 모듈에 import *를 했을 때 어떤 것들이 임포트되는지를 제어할 수 있습니다. 그래도 여전히 import * 만 봐서는 정확히 어떤 것들이 임포트되는지를 알 수 없기 때문에 import *는 프로그램에서 정의되는 이름들, 즉 네임스페이스를 완벽히 이해하고 있을 때만 사용하는 것을 추천드립니다.

     

    6. Reference

    Codeit 강의 파이썬 중급 교육 자료

    반응형

    관련된 글 보기

    Comments