Coding Diary.

(파이썬) 패키지의 개념과 임포트(import)하는 여러 가지 방법, init 파일, all 특수 변수 총정리 본문

Coding/Python

(파이썬) 패키지의 개념과 임포트(import)하는 여러 가지 방법, init 파일, all 특수 변수 총정리

life-of-nomad 2024. 6. 16. 15:53
728x90
반응형
지난 글에서 모듈과 스크립트의 차이점에 대해 알아보았습니다. 이번 글에서는 모듈을 모아놓은 디렉토리인 패키지와 임포트 하는 방법, init 파일, 특수변수 __all__ 에 대해 알아보겠습니다.

 

🔻(참고)모듈과 스크립트🔻

 

(파이썬) 모듈과 스크립트의 차이점 총정리

1. 모듈모듈은 여러 기능을 모아둔 파이썬 파일입니다.예를 들어, 평면도형의 면적을 구해주는 함수들을 모아서 area라는 모듈을 만들겠습니다.PI = 3.14# 원의 면적을 구해 주는 함수def circle(radius):

life-of-nomad.tistory.com

 

1. 패키지란?

  • 패키지는 모듈을 모아 놓은 디렉토리를 뜻합니다.
  • 예를 들어, 평면도형의 면적을 구해주는 area 모듈과 입체도형의 부피를 구해주는 volume 모듈을 모아서 shapes 라는 패키지를 만들었습니다. shapes 패키지 및 디렉토리 구조는 아래와 같습니다.
shapes/
    __init__.py
    area.py
    volume.py
run.py
<shapes/area.py>

# 원의 면적을 구해 주는 함수
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
  • 패키지는 일반 디렉토리와 똑같은데, 안에 __init__.py 라는 파일이 있습니다.

 

2. 패키지 임포트

  • 모듈과 비슷하게 패키지 안에 있는 내용을 가져올 때도 import 키워드를 사용합니다.

1) import <package.module>

<run.py>

import shapes.volume

print(shapes.volume.cube(3))
  • 이렇게 패키지 안에 있는 모듈을 가져올 수 있습니다.
  • 패키지나 모듈 안에 있는 것은 항상 .을 이용해서 접근합니다.

2) import <package>

<run.py>

import shapes

print(shapes.volume.cube(3)) #오류
  • 이렇게 패키지 자체를 임포트할 수도 있는데 그러면 패키지 안에 있는 내용들은 임포트되지 않습니다. 
  • 패키지 안에 있는 모듈도 같이 임포트하려면 패키지의 init 파일을 활용해야 합니다. (아래에서 설명)
  • 따라서 위의 코드는 오류가 납니다.
  • 참고로 import ... 방식을 써서는 모듈의 함수나 변수를 바로 가져올 수 없습니다.
<run.py>

import shapes.volume.cube #오류
  • import ... 방식으로는 패키지나 모듈만 임포트할 수 있습니다.

3) from <package> import <module(s)>

<run.py>

from shapes import volume
print(volume.cube(3))
  • from ... import ... 방식도 패키지에 쓸 수 있습니다.
  • 패키지 안의 모듈을 바로 가져올 수도 있습니다.

4) from <package.module> import <member(s)>

  • 모듈 안에 있는 변수나 함수를 가져올 수도 있습니다.
<run.py>

from shapes.volume import cube

print(cube(3))

5) as 키워드

  • 임포트 문 뒤에 as 키워드를 써서 임포트하는 것의 이름을 바꿔줄 수도 있습니다.
<run.py>

import shapes.volume as vol

print(vol.cube(3))

 

3. __init__ 파일

1) __init__ 파일이란?

  • 패키지 안에는 __init__.py 라는 파일이 있습니다. 이 파일은 '이 폴더는 파이썬 패키지다' 라고 말해 주는 파일입니다.
  • 파이썬 3.3 이전 버전에서는 init 파일이 필수였습니다. 디렉토리 안에 init 파일이 없으면 디렉토리가 패키지로 인식되지 않아서 패키지를 임포트할 수 없었습니다.
  • 파이썬 3.3 이후 버전부터는 init 파일이 필수가 아니게 됐지만 파이썬 하위 버전과의 호환성과 패키지의 명확성을 위해 항상 패키지 안에 init 파일을 만들어 주는 것이 좋습니다.
  • init은 initialize 라는 단어를 줄인건데, 초기화를 뜻합니다. 
  • 우리가 처음으로 패키지나 패키지 안에 있는 어떤 것을 임포트하면 가장 먼저 패키지의 init 파일에 있는 코드가 실행됩니다.

2) __init__ 파일에서 임포트 사용하기

  • 패키지를 임포트하면 기본적으로 패키지 안에 있는 내용은 임포트되지 않습니다.
  • 패키지를 임포트할 때 패키지 안에 있는 내용도 함께 임포트 하고 싶다면 init 파일을 활용해야 합니다.
  • init 파일에 패키지와 함께 임포트하고 싶은 것들을 써주면 됩니다.
<shapes/__init__py>

from shapes import area, volume
  • 그러면 이제 shapes 패키지를 임포트하면 area랑 volume 모듈도 임포트 됩니다.
  • init 파일에서 임포트하는 것은 패키지 안으로 임포트됩니다. 
  • area랑 volume 모듈을 아래와 같이 접근할 수 있습니다.
<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) __init__ 파일에서 변수 정의하기

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

  • 모듈을 임포트 할 때 from <module> import * 를 하면 모듈의 모든 내용이 임포트됩니다.
  • 하지만 모듈 대신 패키지에 from <package> import * 를 하면 패키지 않에 있는 게 아무것도 임포트되지 않습니다.

1) __all__ 특수변수

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

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 모듈의 모든 내용이 임포트되지 않고 circle 과 square 함수만 임포트됩니다.

3) __all__ 과 패키지

  • 패키지의 __all__ 은 패키지에 해당하는 init 파일에서 정의됩니다.
  • 예를 들어 shapes 패키지의 init 파일에 아래와 같은 코드를 추가해주면
<shapes/__init__.py>

# __all__ 정의
__all__ = ['area', 'volume']
  • from shapes import * 를 하면 area 모듈과 volume 모듈이 임포트 됩니다.
  • __all__을 사용하면 패키지나 모듈에 import * 를 했을 때 어떤 것들이 임포트되는 지를 제어할 수 있습니다 .
  • 그래도 여전히 import * 만 봐서는 정확히 어떤 것들이 임포트되는지를 알 수 없기 때문에 import *는 프로그램에서 정의 되는 이름들, 즉 네임스페이스를 완벽히 이해하고 있을 때만 사용하는게 좋습니다.
728x90
반응형