Unit 44. 모듈과 패키지 사용하기
지금까지 파이썬 코드를 작성하면서 input, print 등의 내장 함수(built-in function)를 주로 사용했는데, 내장 함수만으로는 할 수 있는게 별로 없습니다. 그래서 좀 더 복잡한 프로그램을 만들려면 파이썬의 모듈과 패키지를 사용해야 합니다. 우리가 책 중간 중간에 사용했던 random, turtle, pickle 등이 바로 모듈과 패키지입니다.
모듈(module)은 각종 변수, 함수, 클래스를 담고 있는 파일이고, 패키지(package)는 여러 모듈을 묶은 것입니다. 파이썬을 설치할 때 다양한 모듈과 패키지가 기본으로 설치됩니다. 만약 기본 모듈과 패키지로 부족하다면 다른 사람이 만든 유명 모듈과 패키지를 설치해서 쓸 수도 있습니다.
파이썬을 배우다 보면 모듈, 패키지, 파이썬 표준 라이브러리와 같은 용어를 접하게 되는데 서로 비슷한 개념이지만 약간의 차이가 있습니다.
모듈: 특정 기능을 .py 파일 단위로 작성한 것입니다.
패키지: 특정 기능과 관련된 여러 모듈을 묶은 것입니다. 패키지는 모듈에 네임스페이스(namespace, 이름공간)를 제공합니다.
파이썬 표준 라이브러리: 파이썬에 기본으로 설치된 모듈과 패키지, 내장 함수를 묶어서 파이썬 표준 라이브러리(Python Standard Library, PSL)라 부릅니다.
44.1 import로 모듈 가져오기
모듈은 import 키워드로 가져올 수 있습니다(모듈을 여러 개 가져올 때는 모듈을 콤마로 구분).
- import 모듈
- import 모듈1, 모듈2
- 모듈.변수
- 모듈.함수()
- 모듈.클래스()
그럼 간단하게 파이썬 표준 라이브러리의 수학 모듈 math를 가져와서 원주율을 출력해보겠습니다.
>>> import math
>>> math.pi
3.141592653589793
import에 모듈 이름을 지정하면 해당 모듈을 가져올 수 있으며 math.pi와 같이 모듈.변수 형식으로 모듈의 변수를 사용합니다.
이번에는 math 모듈의 제곱근 함수 sqrt를 사용해보겠습니다.
>>> import math
>>> math.sqrt(4.0)
2.0
>>> math.sqrt(2.0)
1.4142135623730951
모듈의 함수는 math.sqrt(4.0)와 같이 모듈.함수() 형식으로 사용합니다.
ModuleNotFoundError: No module named ...: 모듈의 이름이 잘못되었을 때 발생하는 에러입니다. 모듈 이름이 맞는지 확인해주세요.
AttributeError: module ... has no attribute ...: 모듈의 변수나 함수의 이름을 잘못되었을 때 발생하는 에러입니다. 변수, 함수의 이름이 맞는지 확인해주세요.
44.1.1 import as로 모듈 이름 지정하기
모듈의 함수를 사용할 때 math.sqrt처럼 일일이 math를 입력하기 귀찮은 사람도 있겠죠? 이때는 import as를 사용하여 모듈의 이름을 지정할 수 있습니다.
- import 모듈 as 이름
이제 math 모듈을 m으로 줄여보겠습니다.
>>> import math as m # math 모듈을 가져오면서 이름을 m으로 지정
>>> m.sqrt(4.0) # m으로 제곱근 함수 사용
2.0
>>> m.sqrt(2.0) # m으로 제곱근 함수 사용
1.4142135623730951
import math as m과 같이 모듈을 가져오면서 as 뒤에 이름을 지정해줍니다. 이후 math 모듈을 사용할 때 m으로 줄여서 사용할 수 있습니다.
44.1.2 from import로 모듈의 일부만 가져오기
import as로 모듈의 이름을 지정하는 방법보다 좀 더 편한 방법이 있습니다. 이번에는 from import로 원하는 변수만 가져와보겠습니다.
- from 모듈 import 변수
다음은 math 모듈에서 변수 pi만 가져옵니다.
>>> from math import pi # math 모듈에서 변수 pi만 가져옴
>>> pi # pi를 바로 사용하여 원주율 출력
3.141592653589793
from math import pi와 같이 from 뒤에 모듈 이름을 지정하고 import 뒤에 가져올 변수를 입력합니다. 이후 가져온 변수를 사용할 때는 pi와 같이 모듈 이름을 붙이지 않고 바로 사용하면 됩니다.
모듈의 변수를 가져왔으니 이번에는 함수를 가져와보겠습니다(물론 클래스도 가져올 수 있습니다).
- from 모듈 import 함수
- from 모듈 import 클래스
다음은 math 모듈에서 sqrt 함수만 가져옵니다.
>>> from math import sqrt # math 모듈에서 sqrt 함수만 가져옴
>>> sqrt(4.0) # sqrt 함수를 바로 사용
2.0
>>> sqrt(2.0) # sqrt 함수를 바로 사용
1.4142135623730951
math 모듈에서 sqrt 함수만 가져왔으므로 sqrt(4.0)처럼 앞에 math를 붙이지 않고 함수를 바로 사용할 수 있습니다.
지금까지 변수나 함수를 하나만 가져왔습니다. 하지만 math 모듈에서 가져올 변수와 함수가 여러 개일 수도 있겠죠? 이때는 import 뒤에 가져올 변수, 함수, 클래스를 콤마로 구분하여 여러 개를 지정해주면 됩니다.
- from 모듈 import 변수, 함수, 클래스
다음은 math 모듈에서 pi, sqrt를 가져옵니다.
>>> from math import pi, sqrt # math 모듈에서 pi, sqrt를 가져옴
>>> pi # pi로 원주율 출력
3.141592653589793
>>> sqrt(4.0) # sqrt 함수 사용
2.0
>>> sqrt(2.0) # sqrt 함수 사용
1.4142135623730951
from math import pi, sqrt와 같이 pi와 sqrt 두 개를 가져왔습니다. 하지만 변수, 함수, 클래스가 두세 개라면 괜찮지만 수십 개가 된다면 입력하기가 상당히 번거롭겠죠?
from import는 모듈의 모든 변수, 함수, 클래스를 가져오는 기능도 있습니다.
- from 모듈 import *
다음은 math 모듈의 모든 변수, 함수, 클래스를 가져옵니다.
>>> from math import * # math 모듈의 모든 변수, 함수, 클래스를 가져옴
>>> pi # pi로 원주율 출력
3.141592653589793
>>> sqrt(4.0) # sqrt 함수 사용
2.0
>>> sqrt(2.0) # sqrt 함수 사용
1.4142135623730951
from math import *와 같이 지정하면 math 모듈의 모든 함수, 변수, 클래스를 가져옵니다(보통 컴퓨터에서 *(asterisk, 애스터리스크) 기호는 모든 것이라는 뜻으로 사용합니다).
44.1.3 from import로 모듈의 일부를 가져온 뒤 이름 지정하기
이번에는 from import로 변수, 함수, 클래스를 가져온 뒤 이름을 지정해보겠습니다.
- from 모듈 import 변수 as 이름
- from 모듈 import 함수 as 이름
- from 모듈 import 클래스 as 이름
다음은 math 모듈에서 sqrt 함수를 가져오면서 이름을 s로 지정합니다.
>>> from math import sqrt as s # math 모듈에서 sqrt 함수를 가져오면서 이름을 s로 지정
>>> s(4.0) # s로 sqrt 함수 사용
2.0
>>> s(2.0) # s로 sqrt 함수 사용
1.4142135623730951
from import로 가져온 변수, 함수, 클래스 뒤에 as로 이름을 지정해주면 됩니다.
그럼 여러 개를 가져왔을 때 각각 이름을 지정할 수는 없을까요? 이때는 각 변수, 함수, 클래스 등을 콤마로 구분하여 as를 여러 개 지정하면 됩니다.
- from 모듈 import 변수 as 이름1, 함수 as 이름2, 클래스 as 이름3
다음은 math 모듈의 pi를 가져오면서 이름을 p로, sqrt를 가져오면서 이름을 s로 지정합니다.
>>> from math import pi as p, sqrt as s
>>> p # p로 원주율 출력
3.141592653589793
>>> s(4.0) # s로 sqrt 함수 사용
2.0
>>> s(2.0) # s로 sqrt 함수 사용
1.4142135623730951
이처럼 as를 사용하면 모듈의 이름을 원하는 대로 지정해서 사용할 수 있습니다.
import로 가져온 모듈(변수, 함수, 클래스)은 del로 해제할 수 있습니다.
>>> import math
>>> del math
모듈을 다시 가져오려면 importlib.reload를 사용합니다.
>>> import importlib
>>> import math
>>> importlib.reload(math)
44.2 import로 패키지 가져오기
패키지는 특정 기능과 관련된 여러 모듈을 묶은 것인데, 패키지에 들어있는 모듈도 import를 사용하여 가져옵니다.
- import 패키지.모듈
- import 패키지.모듈1, 패키지.모듈2
- 패키지.모듈.변수
- 패키지.모듈.함수()
- 패키지.모듈.클래스()
여기서는 파이썬 표준 라이브러리에서 urllib 패키지의 request 모듈을 가져와보겠습니다(urllib은 URL 처리에 관련된 모듈을 모아 놓은 패키지입니다).
>>> import urllib.request
>>> response = urllib.request.urlopen('http://www.google.co.kr')
>>> response.status
200
패키지에 들어있는 모듈은 import urllib.request와 같이 패키지.모듈 형식으로 가져옵니다. 마찬가지로 모듈의 함수를 사용할 때도 urllib.request.urlopen()과 같이 패키지.모듈.함수() 형식으로 패키지 이름과 모듈 이름을 모두 입력해줍니다.
이 예제는 패키지 사용을 학습하기 위한 것이므로, urllib.request.urlopen 함수의 사용 방법은 이해하지 않고 그냥 넘어가도 됩니다.
urllib.request.urlopen은 URL을 여는 함수인데 URL 열기에 성공하면 response.status의 값이 200이 나옵니다. 이 200은 HTTP 상태 코드이며 웹 서버가 요청을 제대로 처리했다는 뜻입니다.
44.2.1 import as로 패키지 모듈 이름 지정하기
패키지 안에 들어있는 모듈도 import as를 사용하여 이름을 지정할 수 있습니다.
- import 패키지.모듈 as 이름
다음은 urllib 패키지의 request 모듈을 가져오면서 이름을 r로 지정합니다.
>>> import urllib.request as r # urllib 패키지의 request 모듈을 가져오면서 이름을 r로 지정
>>> response = r.urlopen('http://www.google.co.kr') # r로 urlopen 함수 사용
>>> response.status
200
패키지 이름에 모듈 이름까지 더하면 상당히 길어지는데 import as를 사용하니 코드가 좀 더 간단해졌죠?
44.2.2 from import로 패키지의 모듈에서 일부만 가져오기
패키지도 from import를 사용하여 모듈에서 변수, 함수, 클래스를 가져올 수 있습니다.
- from 패키지.모듈 import 변수
- from 패키지.모듈 import 함수
- from 패키지.모듈 import 클래스
- from 패키지.모듈 import 변수, 함수, 클래스
다시 urllib 패키지의 request 모듈에서 urlopen 함수와 Request 클래스를 가져와 보겠습니다.
>>> from urllib.request import Request, urlopen # urlopen 함수, Request 클래스를 가져옴
>>> req = Request('http://www.google.co.kr') # Request 클래스를 사용하여 req 생성
>>> response = urlopen(req) # urlopen 함수 사용
>>> response.status
200
참고로 urlopen 함수에 URL을 바로 넣어도 되고, Request('http://www.google.co.kr')와 같이 Request 클래스에 URL을 넣은 뒤에 req를 생성해서 urlopen 함수에 넣어도 됩니다.
패키지의 모듈에서 모든 변수, 함수, 클래스를 가져오는 방법은 다음과 같습니다.
- from 패키지.모듈 import *
다음은 urllib의 request 모듈에서 모든 변수, 함수, 클래스를 가져옵니다.
>>> from urllib.request import * # urllib의 request 모듈에서 모든 변수, 함수, 클래스를 가져옴
>>> req = Request('http://www.google.co.kr') # Request를 사용하여 req 생성
>>> response = urlopen(req) # urlopen 함수 사용
>>> response.status
200
44.2.3 from import로 패키지의 모듈의 일부를 가져온 뒤 이름 지정하기
이번에는 from import로 패키지의 모듈에서 변수, 함수, 클래스를 가져온 뒤 이름을 지정해보겠습니다.
- from 패키지.모듈 import 변수 as 이름
- from 패키지.모듈 import 변수 as 이름, 함수 as 이름, 클래스 as 이름
다음은 urllib 패키지의 request 모듈에서 Request 클래스를 가져온 뒤 이름을 r로 지정하고, urlopen 함수를 가져온 뒤 이름을 u로 지정합니다.
>>> from urllib.request import Request as r, urlopen as u
>>> req = r('http://www.google.co.kr') # r로 Request 클래스 사용
>>> response = u(req) # u로 urlopen 함수 사용
>>> response.status
200
44.3 파이썬 패키지 인덱스에서 패키지 설치하기
파이썬은 파이썬 표준 라이브러리(Python Standard Library, PSL) 이외에도 파이썬 패키지 인덱스(Python Package Index, PyPI)를 통해 다양한 패키지를 사용할 수 있습니다. 특히 명령만 입력하면 원하는 패키지를 인터넷에서 다운로드하여 설치해줄 뿐만 아니라 관련된 패키지(의존성)까지 자동으로 설치해주므로 매우 편리합니다.
44.3.1 pip 설치하기
pip는 파이썬 패키지 인덱스의 패키지 관리 명령어이며 Windows용 파이썬에는 기본으로 내장되어 있습니다. 리눅스와 macOS에서는 콘솔(터미널)에서 다음과 같은 방법으로 설치하면 됩니다.
리눅스, macOS
$ curl -O https://bootstrap.pypa.io/get-pip.py
$ sudo python3 get-pip.py
만약 리눅스에 curl이 설치되어 있지 않다면 다음과 같은 방법으로 설치해줍니다.
우분투
$ sudo apt-get install curl
CentOS
$ sudo yum install curl
44.3.2 pip로 패키지 설치하기
이제 pip install 명령으로 패키지를 설치해보겠습니다.
- pip install 패키지
Windows에서는 명령 프롬프트를 실행(윈도우 키+R을 누른 뒤 cmd를 입력)하고, 리눅스와 macOS에서는 콘솔(터미널)을 실행한 뒤 pip install requests 명령을 입력합니다(pip 명령은 파이썬 셸 >>>에 입력하면 안 됩니다. 반드시 명령 프롬프트, 콘솔, 터미널에 입력해주세요).
참고로 requests는 파이썬 표준 라이브러리의 urllib.request와 비슷한 역할을 하는 패키지인데 좀 더 기능이 많고 편리합니다.
Windows
C:\Users\dojang>pip install requests
리눅스, macOS에서는 앞에 sudo를 붙여서 관리자 권한으로 실행합니다.
리눅스, macOS
$ sudo pip install requests
또는, python에 -m 옵션을 지정해서 pip를 실행할 수도 있습니다. -m 옵션은 모듈을 실행하는 옵션이며 pip도 모듈입니다.
Windows
C:\Users\dojang>python -m pip install requests
리눅스, macOS에서는 python3으로 실행하고, 앞에 sudo를 붙여서 관리자 권한으로 실행합니다.
리눅스, macOS
$ sudo python3 -m pip install requests
명령을 입력하면 패키지 다운로드 및 설치 상황이 표시되는데, 다음과 같이 출력되면 정상적으로 설치된 것입니다(패키지는 계속 업데이트되므로 버전은 책과 다를 수 있습니다).
Collecting requests
Downloading requests-2.9.1-py2.py3-none-any.whl (501kB)
100% |################################| 503kB 974kB/s
Installing collected packages: requests
Successfully installed requests-2.9.1
44.3.3 import로 패키지 가져오기
이제 파이썬 코드에서 패키지를 사용해보겠습니다.
- import 패키지
>>> import requests # pip로 설치한 requests 패키지를 가져옴
>>> r = requests.get('http://www.google.co.kr') # requests.get 함수 사용
>>> r.status_code
200
보통 pip install 명령으로 설치한 패키지는 import 패키지 또는 import 패키지.모듈 형식으로 사용하면 됩니다. 단, 패키지마다 구성이 다를 수 있으므로 해당 패키지의 웹 사이트에서 사용 방법을 찾아보기 바랍니다.
지금까지 모듈을 가져오고 사용하는 방법을 배웠습니다. 특히 from import는 코드를 간단하게 줄일 수 있어서 파이썬 스크립트에서 자주 볼 수 있습니다. 따라서 from import 사용 방법을 꼭 익혀 두는 것이 좋습니다.
보통 리눅스와 macOS에서는 파이썬 버전 2와 3와 함께 설치된 경우가 많습니다. 그래서 파이썬 실행 파일을 python, python3와 같이 구분하죠. 마찬가지로 pip도 파이썬 버전을 붙이고 있으며 파이썬 버전에 맞게 사용해야 합니다(다른 버전에 설치된 패키지는 가져와서 사용할 수 없습니다).
파이썬 2에서는 pip 또는 pip2 명령을 사용하여 패키지를 설치합니다.
파이썬 2
$ sudo python -m pip install 패키지
$ sudo pip install 패키지
파이썬 3에서는 pip 또는 pip3 명령을 사용하여 패키지를 설치합니다(파이썬 2 없이 파이썬 3가 기본 설치된 경우에는 pip가 파이썬 3용 명령).
파이썬 3
$ sudo python3 -m pip install 패키지
$ sudo pip3 install 패키지
파이썬 2와 3 모두 버전이 붙지 않은 pip 명령을 제공하지만 이름이 같으므로 구분하기가 힘듭니다. 가급적이면 파이썬은 한 개의 버전만 설치하는 것이 좋으며 여러 버전을 설치한 경우 pip2, pip3과 같이 버전을 붙여서 실행합니다.
pip search 패키지: 패키지 검색
pip install 패키지==버전: 특정 버전의 패키지를 설치(예: pip install requests==2.9.0)
pip list 또는 pip freeze: 패키지 목록 출력
pip uninstall 패키지: 패키지 삭제
44.5 연습문제: 소수점 이하 올림, 버림 구하기
다음 소스 코드를 완성하여 소수점 이하를 올림, 버림한 숫자가 출력되게 만드세요. 올림 함수는 math 모듈의 ceil, 버림 함수는 math 모듈의 floor 함수입니다.
practice_import.py
x = 1.5
print(ceil(x), floor(x))
실행 결과
2 1
정답
from math import ceil, floor
해설
올림 함수 ceil, 버림 함수 floor를 사용할 때 모듈 이름을 지정하지 않고 그대로 사용하고 있습니다. 따라서 from math import ceil, floor와 같이 from import로 두 함수를 가져오면 됩니다. 또는, from math import *와 같이 math의 모든 변수, 함수, 클래스를 가져와도 됩니다.
표준 입력으로 원의 반지름(실수)이 입력됩니다. 입력된 반지름을 이용하여 원의 넓이를 출력하는 프로그램을 만드세요(input에서 안내 문자열은 출력하지 않아야 합니다). 원의 넓이는 반지름 * 반지름 * 원주율로 구합니다.
judge_import.py
________________
________________
________________
정답
r = float(input())
print(math.pi*r*r)
45.1 모듈 만들기
Unit 45. 모듈과 패키지 만들기
파이썬 스크립트를 작성할 때마다 매번 비슷한 클래스와 함수를 작성한다면 코드도 길어지고 중복되는 부분이 생깁니다. 이런 경우에는 공통되는 부분을 빼내서 모듈과 패키지로 만들면 됩니다. 이후에는 코드를 다시 만들지 않고 모듈과 패키지만 가져와서 사용하면 편리합니다.
모듈(module)은 변수, 함수, 클래스 등을 모아 놓은 스크립트 파일이고, 패키지(package)는 여러 모듈을 묶은 것입니다. 모듈은 간단한 기능을 담을 때 사용하며, 패키지는 코드가 많고 복잡할 때 사용합니다. 즉, 패키지는 기능들이 모듈 여러 개로 잘게 나누어져 있고, 관련된 모듈끼리 폴더에 모여 있는 형태입니다.
이번 유닛에서는 파이썬의 모듈과 패키지를 직접 만들어보겠습니다.
45.1 모듈 만들기
그럼 간단하게 2의 거듭제곱을 구하는 모듈을 만들어보겠습니다. 다음 내용을 프로젝트 폴더(C:\project) 안에 square2.py 파일로 저장합니다. IDLE에서 새 소스 파일을 만들고 저장하는 방법은 '3.2 IDLE에서 소스 파일 실행하기'를 참조하세요.
square2.py
base = 2 # 변수
def square(n): # 함수
return base ** n
이렇게 변수와 함수를 넣어서 square2.py 파일을 만들었습니다. 이렇게 모듈을 만들었을 때 모듈 이름은 square2입니다. 즉, 스크립트 파일에서 확장자 .py를 제외하면 모듈 이름이 됩니다.
45.1.1 모듈 사용하기
이제 square2 모듈을 사용해보겠습니다. 다음 내용을 프로젝트 폴더(C:\project) 안에 main.py 파일로 저장한 뒤 실행해보세요. 이때 square2.py 파일과 main.py 파일은 반드시 같은 폴더에 있어야 합니다.
- import 모듈
- 모듈.변수
- 모듈.함수()
main.py
import square2 # import로 square2 모듈을 가져옴
print(square2.base) # 모듈.변수 형식으로 모듈의 변수 사용
print(square2.square(10)) # 모듈.함수() 형식으로 모듈의 함수 사용
실행 결과
2
1024
실행을 해보면 square2 모듈에 만들었던 변수 base의 값이 출력되고, square 함수도 호출됩니다. 이처럼 모듈을 사용할 때는 import로 모듈을 가져온 뒤 모듈.변수, 모듈.함수() 형식으로 사용합니다.
45.1.2 from import로 변수, 함수 가져오기
물론 모듈에서 from import로 변수와 함수를 가져온 뒤 모듈 이름을 붙이지 않고 사용할 수도 있습니다.
- from 모듈 import 변수, 함수
>>> from square2 import base, square
>>> print(base)
2
>>> square(10)
1024
45.1.3 모듈에 클래스 작성하기
그럼 이번에는 모듈에 클래스를 작성하고 사용해보겠습니다. 다음 내용을 프로젝트 폴더(C:\project) 안에 person.py 파일로 저장하세요.
person.py
class Person: # 클래스
def __init__(self, name, age, address):
self.name = name
self.age = age
self.address = address
def greeting(self):
print('안녕하세요. 저는 {0}입니다.'.format(self.name))
이제 main.py 파일을 다음과 같이 고쳐서 실행해보세요.
- import 모듈
- 모듈.클래스()
main.py
import person # import로 person 모듈을 가져옴
# 모듈.클래스()로 person 모듈의 클래스 사용
maria = person.Person('마리아', 20, '서울시 서초구 반포동')
maria.greeting()
실행 결과
안녕하세요. 저는 마리아입니다.
모듈의 클래스를 사용하는 방법도 변수, 함수와 같습니다. 즉, 모듈.클래스() 형식으로 모듈의 클래스를 사용하며, 클래스로 인스턴스를 만들 때는 person.Person('마리아', 20, '서울시 서초구 반포동')와 같이 사용하면 됩니다.
45.1.4 from import로 클래스 가져오기
물론 모듈에서 from import로 클래스를 가져온 뒤 모듈 이름을 붙이지 않고 사용할 수도 있습니다.
- from 모듈 import 클래스
>>> from person import Person
>>> maria = Person('마리아', 20, '서울시 서초구 반포동')
>>> maria.greeting()
안녕하세요. 저는 마리아입니다.
지금까지 만든 square2, person 모듈을 그림으로 나타내면 다음과 같은 모양이 됩니다.
▼ 그림 45-1 모듈 사용하기
45.2 모듈과 시작점 알아보기
인터넷에 있는 파이썬 코드를 보다 보면 if __name__ == '__main__':으로 시작하는 부분을 자주 만나게 됩니다.
if __name__ == '__main__':
코드
도대체 이 코드는 왜 사용하는 것일까요? 이 코드는 현재 스크립트 파일이 실행되는 상태를 파악하기 위해 사용합니다.
먼저 __name__부터 알아보겠습니다. 다음 내용을 프로젝트 폴더(C:\project) 안에 hello.py 파일로 저장하세요.
hello.py
print('hello 모듈 시작')
print('hello.py __name__:', __name__) # __name__ 변수 출력
print('hello 모듈 끝')
그리고 다음 내용을 프로젝트 폴더(C:\project) 안에 main.py 파일로 저장한 뒤 실행해보세요.
main.py
import hello # hello 모듈을 가져옴
print('main.py __name__:', __name__) # __name__ 변수 출력
실행 결과
hello 모듈 시작
hello.py __name__: hello
hello 모듈 끝
main.py __name__: __main__
실행을 해보면 hello.py 파일과 main.py 파일의 __name__ 변수 값이 출력됩니다.
파이썬에서 import로 모듈을 가져오면 해당 스크립트 파일이 한 번 실행됩니다. 따라서 hello 모듈을 가져오면 hello.py 안의 코드가 실행됩니다. 따라서 hello.py의 __name__ 변수에는 'hello'가 들어가고, main.py의 __name__ 변수에는 '__main__'이 들어갑니다.
▼ 그림 45-2 hello.py를 모듈로 가져왔을 때즉, __name__은 모듈의 이름이 저장되는 변수이며 import로 모듈을 가져왔을 때 모듈의 이름이 들어갑니다. 하지만 파이썬 인터프리터로 스크립트 파일을 직접 실행했을 때는 모듈의 이름이 아니라 '__main__'이 들어갑니다(참고로 __name__과 __main__을 헷갈리지 마세요. 같은 네 글자에 알파벳 모양이 비슷해서 헷갈리기 쉽습니다).
좀 더 정확하게 알아보기 위해 콘솔(터미널, 명령 프롬프트)에서 python으로 main.py 파일을 실행해봅니다(리눅스, macOS에서는 python3 사용).
C:\project>python main.py
hello 모듈 시작
hello.py __name__: hello
hello 모듈 끝
main.py __name__: __main__
python main.py와 같이 파이썬으로 스크립트 파일을 직접 실행했습니다. 여기서도 hello.py 파일의 __name__ 변수에는 'hello' 그리고 main.py 파일의 __name__ 변수에는 '__main__'이 들어갑니다.
▼ 그림 45-3 hello.py를 모듈로 가져왔을 때하지만 다음과 같이 python으로 hello.py 파일을 실행해보면 결과가 조금 달라집니다.
C:\project>python hello.py
hello 모듈 시작
hello.py __name__: __main__
hello 모듈 끝
hello.py 파일의 __name__ 변수에는 'hello'가 아니라 '__main__'이 들어갑니다. 즉, 어떤 스크립트 파일이든 파이썬 인터프리터가 최초로 실행한 스크립트 파일의 __name__에는 '__main__'이 들어갑니다. 이는 프로그램의 시작점(entry point)이라는 뜻입니다.
▼ 그림 45-4 hello.py를 단독으로 실행했을 때파이썬은 최초로 시작하는 스크립트 파일과 모듈의 차이가 없습니다. 어떤 스크립트 파일이든 시작점도 될 수 있고, 모듈도 될 수 있습니다. 그래서 __name__ 변수를 통해 현재 스크립트 파일이 시작점인지 모듈인지 판단합니다.
if __name__ == '__main__':처럼 __name__ 변수의 값이 '__main__'인지 확인하는 코드는 현재 스크립트 파일이 프로그램의 시작점이 맞는지 판단하는 작업입니다. 즉, 스크립트 파일이 메인 프로그램으로 사용될 때와 모듈로 사용될 때를 구분하기 위한 용도입니다.
45.2.1 스크립트 파일로 실행하거나 모듈로 사용하는 코드 만들기
그럼 스크립트 파일을 그대로 실행할 수도 있고, 모듈로도 사용할 수 있는 코드를 만들어보겠습니다. 다음 내용을 프로젝트 폴더(C:\project) 안에 calc.py 파일로 저장한 뒤 실행해보세요.
calc.py
def add(a, b):
return a + b
def mul(a, b):
return a * b
if __name__ == '__main__': # 프로그램의 시작점일 때만 아래 코드 실행
print(add(10, 20))
print(mul(10, 20))
실행 결과
30
200
C:\project>python calc.py
30
200
IDLE에서 실행하거나 python calc.py와 같이 파이썬 인터프리터로 실행하면 10, 20의 합과 곱이 출력됩니다. 즉, 프로그램의 시작점일 때는 if __name__ == '__main__': 아래의 코드가 실행됩니다.
그럼 calc.py를 모듈로 사용하면 어떻게 될까요? 다음과 같이 import로 calc를 가져와봅니다.
>>> import calc
>>>
모듈로 가져왔을 때는 아무것도 출력되지 않습니다. 왜냐하면 __name__ 변수의 값이 '__main__'일 때만 10, 20의 합과 곱을 출력하도록 만들었기 때문입니다. 즉, 스크립트 파일을 모듈로 사용할 때는 calc.add, calc.mul처럼 함수만 사용하는 것이 목적이므로 10, 20의 합과 곱을 출력하는 코드는 필요가 없습니다.
이때는 다음과 같이 calc.add와 calc.mul 함수에 원하는 값을 넣어서 사용하면 됩니다.
>>> calc.add(50, 60)
110
>>> calc.mul(50, 60)
3000
파이썬이 처음에 개발 될 당시에는 리눅스/유닉스에서 사용하는 스크립트 언어 기반이었기 때문에 프로그램의 시작점이 따로 정해져 있지 않았습니다. 보통 리눅스/유닉스의 스크립트 파일은 파일 한 개로 이루어진 경우가 많은데, 이 스크립트 파일 자체가 하나의 프로그램이다 보니 시작점이 따로 필요하지 않습니다. 하지만 C 언어나 자바같은 언어는 처음 만들어질 때부터 소스 파일을 여러 개 사용했기 때문에 여러 소스 파일의 함수들 중에서도 시작 함수(main)를 따로 정해 놓았습니다.
45.3 패키지 만들기
이번에는 패키지를 만들어보겠습니다. 모듈은 스크립트 파일이 한 개지만 패키지는 폴더(디렉터리)로 구성되어 있습니다.
지금부터 만들 패키지의 폴더 구성은 다음과 같습니다.
▼ 그림 45-5 패키지 폴더 구성먼저 프로젝트 폴더(C:\project) 안에 calcpkg 폴더를 만듭니다. 그리고 다음 내용을 calcpkg 폴더 안에 __init__.py 파일로 저장하세요.
calcpkg/__init__.py
# __init__.py 파일은 내용을 비워 둘 수 있음
폴더(디렉터리) 안에 __init__.py 파일이 있으면 해당 폴더는 패키지로 인식됩니다. 그리고 기본적으로 __init__.py 파일의 내용은 비워 둘 수 있습니다(파이썬 3.3 이상부터는 __init__.py 파일이 없어도 패키지로 인식됩니다. 하지만 하위 버전에도 호환되도록 __init__.py 파일을 작성하는 것을 권장합니다).
45.3.1 패키지에 모듈 만들기
이제 calcpkg 패키지에 모듈을 두 개를 만들겠습니다. 첫 번째 모듈은 덧셈, 곱셈 함수가 들어있는 operation 모듈이고, 두 번째 모듈은 삼각형, 사각형의 넓이 계산 함수가 들어있는 geometry 모듈입니다.
먼저 다음 내용을 calcpkg 폴더 안에 operation.py 파일로 저장하세요.
calcpkg/operation.py
def add(a, b):
return a + b
def mul(a, b):
return a * b
그리고 다음 내용을 calcpkg 폴더 안에 geometry.py 파일로 저장하세요.
calcpkg/geometry.py
def triangle_area(base, height):
return base * height / 2
def rectangle_area(width, height):
return width * height
45.3.2 패키지 사용하기
이제 스크립트 파일에서 패키지의 모듈을 사용해보겠습니다. 다음 내용을 프로젝트 폴더(C:\project) 안에 main.py 파일로 저장한 뒤 실행해보세요(main.py 파일을 calcpkg 패키지 폴더 안에 넣으면 안 됩니다).
- import 패키지.모듈
- 패키지.모듈.변수
- 패키지.모듈.함수()
- 패키지.모듈.클래스()
main.py
import calcpkg.operation # calcpkg 패키지의 operation 모듈을 가져옴
import calcpkg.geometry # calcpkg 패키지의 geometry 모듈을 가져옴
print(calcpkg.operation.add(10, 20)) # operation 모듈의 add 함수 사용
print(calcpkg.operation.mul(10, 20)) # operation 모듈의 mul 함수 사용
print(calcpkg.geometry.triangle_area(30, 40)) # geometry 모듈의 triangle_area 함수 사용
print(calcpkg.geometry.rectangle_area(30, 40)) # geometry 모듈의 rectangle_area 함수 사용
실행 결과
30
200
600.0
1200
calcpkg 패키지의 operation 모듈과 geometry 모듈을 가져와서 안에 들어있는 함수를 호출했습니다.
이처럼 패키지의 모듈을 가져올 때는 import 패키지.모듈 형식으로 가져옵니다. 그리고 패키지.모듈.함수() 형식으로 모듈의 함수를 사용합니다(변수와 클래스도 같은 형식).
45.3.3 from import로 패키지의 모듈에서 변수, 함수, 클래스 가져오기
물론 패키지의 모듈에서 from import로 함수(변수, 클래스)를 가져온 뒤 패키지와 모듈 이름을 붙이지 않고 사용할 수도 있습니다.
- from 패키지.모듈 import 변수
- from 패키지.모듈 import 함수
- from 패키지.모듈 import 클래스
다음은 calcpkg 패키지의 operation 모듈에서 add, mul 함수를 가져옵니다.
>>> from calcpkg.operation import add, mul
>>> add(10, 20)
30
>>> mul(10, 20)
200
지금까지 만든 main.py 스크립트 파일과 calcpkg 패키지의 계층을 그림으로 나타내면 다음과 같은 모양이 됩니다. main.py 파일이 있는 폴더에 calcpkg 패키지가 있고, calcpkg 패키지의 폴더 안에 __init__.py, operation.py, geometry.py 파일이 들어있습니다.
▼ 그림 45-6 calcpkg 패키지의 계층패키지의 모듈에서는 __name__ 변수에 패키지.모듈 형식으로 이름이 들어갑니다. 즉, calcpkg 패키지의 geometry.py에서 __name__의 값을 출력하도록 만들고, import로 가져오면 'calcpkg.geometry'가 나옵니다.
지금까지 모듈과 패키지는 현재 폴더(디렉터리)에 만들었습니다. 파이썬에서는 현재 폴더에 모듈, 패키지가 없으면 다음 경로에서 모듈, 패키지를 찾습니다.
>>> import sys
>>> sys.path
['C:\\project',
'C:\\Users\\dojang\\AppData\\Local\\Programs\\Python\\Python36-32\\Lib\\idlelib', 'C:\\Users\\dojang\\AppData\\Local\\Programs\\Python\\Python36-32\\python36.zip', 'C:\\Users\\dojang\\AppData\\Local\\Programs\\Python\\Python36-32\\DLLs', 'C:\\Users\\dojang\\AppData\\Local\\Programs\\Python\\Python36-32\\lib', 'C:\\Users\\dojang\\AppData\\Local\\Programs\\Python\\Python36-32', 'C:\\Users\\dojang\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\site-packages']
sys 모듈의 path 변수에는 모듈, 패키지를 찾는 경로가 들어있습니다. 여기서 site-packages 폴더에는 pip로 설치한 패키지가 들어갑니다. 그리고 자기가 만든 모듈, 패키지도 site-packages 폴더에 넣으면 스크립트 파일이 어디에 있든 모듈, 패키지를 사용할 수 있습니다.
만약 가상 환경(virtual environment)를 만들어서 모듈과 패키지를 관리한다면 가상환경/Lib/site-packages 폴더에 모듈과 패키지가 들어갑니다. 자세한 내용은 '부록 47.11 가상환경 사용하기'를 참조하세요.
45.4 패키지에서 from import 응용하기
지금까지 calcpkg 패키지의 모듈을 가져올 때 import calcpkg.operation처럼 import 패키지.모듈 형식으로 가져왔습니다. 그러면 import calcpkg처럼 import 패키지 형식으로 패키지만 가져와서 모듈을 사용할 수는 없을까요? 이때는 calcpkg 패키지의 __init__.py 파일을 다음과 같이 수정합니다.
- from . import 모듈
calcpkg/__init__.py
from . import operation # 현재 패키지에서 operation 모듈을 가져옴
from . import geometry # 현재 패키지에서 geometry 모듈을 가져옴
파이썬에서 __init__.py 파일은 폴더(디렉터리)가 패키지로 인식되도록 하는 역할도 하고, 이름 그대로 패키지를 초기화하는 역할도 합니다. 즉, import로 패키지를 가져오면 __init__.py 파일이 실행되므로 이 파일에서 from . import 모듈 형식으로 현재 패키지에서 모듈을 가져오게 만들어야 합니다. 참고로 .(점)은 현재 패키지라는 뜻입니다.
이제 main.py에서 import calcpkg와 같이 패키지만 가져오도록 수정한 뒤 실행해봅니다.
main.py
import calcpkg # calcpkg 패키지만 가져옴
print(calcpkg.operation.add(10, 20)) # operation 모듈의 add 함수 사용
print(calcpkg.operation.mul(10, 20)) # operation 모듈의 mul 함수 사용
print(calcpkg.geometry.triangle_area(30, 40)) # geometry 모듈의 triangle_area 함수 사용
print(calcpkg.geometry.rectangle_area(30, 40)) # geometry 모듈의 rectangle_area 함수 사용
실행 결과
30
200
600.0
1200
calcpkg의 __init__.py에서 하위 모듈을 함께 가져오게 만들었으므로 import calcpkg로 패키지만 가져와도 calcpkg.operation.add(10, 20)처럼 사용할 수 있습니다.
45.4.1 from import로 패키지에 속한 모든 변수, 함수, 클래스 가져오기
앞에서 from import 문법 중에 *(애스터리스크)를 지정하여 모든 변수, 함수, 클래스를 가져오는 방법이 있었습니다. 그럼 패키지에 속한 모든 변수, 함수, 클래스를 가져오려면 어떻게 해야 할까요? 먼저 main.py에서 import calcpkg를 from calcpkg import *와 같이 수정하고, 각 함수들도 앞에 붙은 calcpkg.operation, calcpkg.geometry를 삭제한 뒤 실행해봅니다.
- from 패키지 import *
main.py
from calcpkg import * # calcpkg 패키지의 모든 변수, 함수, 클래스를 가져옴
print(add(10, 20)) # operation 모듈의 add 함수 사용
print(mul(10, 20)) # operation 모듈의 mul 함수 사용
print(triangle_area(30, 40)) # geometry 모듈의 triangle_area 함수 사용
print(rectangle_area(30, 40)) # geometry 모듈의 rectangle_area 함수 사용
실행 결과
Traceback (most recent call last):
File "C:\project\main.py", line 3, in <module>
print(add(10, 20)) # operation 모듈의 add 함수 사용
NameError: name 'add' is not defined
실행을 해보면 add가 정의되지 않았다면서 에러가 발생합니다. 왜냐하면 __init__.py에서 모듈만 가져왔을 뿐 모듈 안의 함수는 가져오지 않았기 때문입니다.
IDLE의 파이썬 프롬프트에서 dir 함수를 호출하여 현재 네임스페이스(namespace, 이름공간)를 확인해봅니다(main.py 안에서 print(dir())을 호출하고 main.py를 실행해도 됨).
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'geometry', 'operation']
현재 네임스페이스에는 operation, geometry만 들어있어서 add, mul처럼 함수 이름만으로는 호출할 수가 없습니다.
이때는 __init__.py에서 모듈 안의 함수를 가져오게 만들어야 합니다. 특히 현재 패키지(calcpkg)라는 것을 명확하게 나타내기 위해 모듈 앞에 .(점)을 붙입니다.
- from .모듈 import 변수, 함수, 클래스
calcpkg/__init__.py
# 현재 패키지의 operation, geometry 모듈에서 각 함수를 가져옴
from .operation import add, mul
from .geometry import triangle_area, rectangle_area
이제 main.py 파일을 실행해보면 결과도 잘 출력되고 add, mul, triangle_area, rectangle_area처럼 함수 이름 그대로 호출할 수 있습니다.
실행 결과
30
200
600.0
1200
물론 __init__.py 파일에서 특정 함수(변수, 클래스)를 지정하지 않고 *을 사용해서 모든 함수(변수, 클래스)를 가져와도 상관없습니다.
- from .모듈 import *
calcpkg/__init__.py
from .operation import * # 현재 패키지의 operation 모듈에서 모든 변수, 함수, 클래스를 가져옴
from .geometry import * # 현재 패키지의 geometry 모듈에서 모든 변수, 함수, 클래스를 가져옴
이렇게 패키지의 __init__.py에서 from .모듈 import 변수, 함수, 클래스 또는 from .모듈 import * 형식으로 작성했다면 패키지를 가져오는 스크립트에서는 패키지.함수() 형식으로 사용할 수 있습니다(변수, 클래스도 같은 형식). 이때는 import calcpkg와 같이 패키지만 가져오면 됩니다.
- import 패키지
- 패키지.변수
- 패키지.함수()
- 패키지.클래스()
main.py
import calcpkg # calcpkg 패키지만 가져옴
print(calcpkg.add(10, 20)) # 패키지.함수 형식으로 operation 모듈의 add 함수 사용
print(calcpkg.mul(10, 20)) # 패키지.함수 형식으로 operation 모듈의 mul 함수 사용
print(calcpkg.triangle_area(30, 40)) # 패키지.함수 형식으로 geometry 모듈의 triangle_area 함수 사용
print(calcpkg.rectangle_area(30, 40))# 패키지.함수 형식으로 geometry 모듈의 rectangle_area 함수 사용
실행 결과
30
200
600.0
1200
__init__.py에서 from .모듈 import 변수, 함수, 클래스 또는 from .모듈 import * 형식으로 모듈을 가져오면 calcpkg 패키지의 네임스페이스에는 add, mul, triangle_area, rectangle_area가 들어갑니다. 따라서 모듈을 거치지 않고 calcpkg.add처럼 패키지에서 함수를 바로 사용할 수 있습니다.
지금까지 모듈과 패키지를 만드는 방법을 배웠습니다. 여기서는 스크립트가 프로그램의 시작점일 때와 모듈일 때를 판단하고 활용하는 부분이 중요합니다. 지금 당장은 모듈과 패키지를 만들 일이 많지 않으므로 모듈과 패키지 작성 방법은 그냥 넘어가도 됩니다. 나중에 모듈과 패키지를 만들어야 할 때 다시 돌아와서 찾아보면 됩니다.
패키지의 __init__.py에서 from .모듈 import *로 모든 변수, 함수, 클래스를 가져오면 패키지 외부에 공개하고 싶지 않은 것까지 공개하게 됩니다. 이때는 __all__에 공개할 모듈, 변수, 함수, 클래스를 리스트 형태로 지정해주면 됩니다. __all__이라는 이름 그대로 모든 것(*)을 가져갈 때의 목록을 정합니다.
calcpkg/__init__.py
__all__ = ['add', 'triangle_area'] # calcpkg 패키지에서 add, triangle_area 함수만 공개
from .operation import * # 현재 패키지의 operation 모듈에서 모든 변수, 함수, 클래스를 가져옴
from .geometry import * # 현재 패키지의 geometry 모듈에서 모든 변수, 함수, 클래스를 가져옴
main.py
from calcpkg import * # calcpkg 패키지의 모든 변수, 함수, 클래스를 가져옴
print(add(10, 20)) # add 함수는 공개되어 있으므로 사용할 수 있음
print(mul(10, 20)) # 에러: mul 함수는 공개되어 있지 않으므로 사용할 수 없음
print(triangle_area(30, 40)) # triangle_area 함수는 공개되어 있으므로 사용할 수 있음
print(rectangle_area(30, 40)) # 에러: rectangle_area 함수는 공개되어 있으므로 사용할 수 있음
main.py에서 from calcpkg import *로 패키지의 모든 변수, 함수, 클래스를 가져온다 하더라도 __all__에 지정된 add, triangle_area 함수만 사용할 수 있습니다.
실행 결과
30
Traceback (most recent call last):
File "C:\project\main.py", line 4, in <module>
print(mul(10, 20)) # 에러: mul 함수는 공개되어 있지 않으므로 사용할 수 없음
NameError: name 'mul' is not defined
파이썬의 패키지는 패키지 안에 하위 패키지를 만들 수 있습니다. 즉, 패키지 안에 폴더(디렉터리)를 만들고 __init__.py와 모듈을 넣으면 하위 패키지가 됩니다.
예를 들어서 다음과 같이 calcpkg 안에 operation과 geometry 하위 패키지가 있고, 그 아래에 모듈이 들어있습니다.
import로 하위 패키지의 모듈을 가져올 때는 계층 순서대로 .(점)을 붙여서 가져오면 됩니다.
import 패키지.하위패키지.모듈
즉, import calcpkg.operation.element와 같은 식입니다. 함수를 사용할 때는 calcpkg.operation.element.add(10, 20)이 되겠죠?
만약, import calcpkg처럼 패키지만 가져와서 사용하고 싶다면 calcpkg/__init__.py에서 하위 패키지의 모듈에 들어있는 변수, 함수, 클래스를 모두 가져오게 만들면 됩니다.
calcpkg/__init__.py
from .operation.element import *
from .operation.logic import *
from .geometry.shape import *
from .geometry.vector import *
이렇게 하면 calcpkg.add(10, 20), calcpkg.triangle_area(30, 40) 또는, add(10, 20), triangle_area(30, 40)처럼 사용할 수 있습니다.
참고로 하위 패키지 안에서 옆에 있는 패키지의 요소를 가져와서 사용하려면 ..을 사용해야 합니다. ..은 상위 폴더(디렉터리)라는 뜻이며 ..패키지 또는 ..모듈은 상위 폴더에 있는 패키지, 모듈이라는 뜻입니다. 즉, 현재 패키지와 같은 계층의 패키지 또는 모듈입니다. 그리고 ...은 상위 폴더의 상위 폴더라는 뜻이며 위로 갈 수록 .이 하나씩 늘어납니다.
from ..패키지 import 모듈
from ..패키지.모듈 import 클래스, 변수, 함수
from ..패키지.모듈 import *
예를 들어 calcpkg/geometry/shape.py에서 옆에 있는 calcpkg/operation 패키지의 element 모듈을 사용한다면 다음과 같이 from ..operation import element로 지정해줍니다. 또는, from ..operation.element import mul과 같이 지정하면 mul을 함수 그대로 사용할 수 있습니다.
calcpkg/geometry/shape.py
from ..operation import element # from ..operation.element import mul로도 가능
def triangle_area(base, height):
return element.mul(base, height) / 2 # mul(base, height)로도 가능
def rectangle_area(width, height):
return element.mul(width, height) # mul(width, height)로도 가능
모듈의 독스트링은 모듈 파일의 첫 줄에 """ """(큰따옴표 세 개) 또는 ''' '''(작은따옴표 세 개)를 사용하여 문자열을 넣습니다.
모듈.py
'''모듈의 독스트링'''
패키지의 독스트링은 __init__.py 파일의 첫 줄에 """ """(큰따옴표 세 개) 또는 ''' '''(작은따옴표 세 개)를 사용하여 문자열을 넣습니다.
__init__.py
'''패키지의 독스트링'''
모듈과 패키지의 독스트링을 출력하려면 모듈 또는 패키지의 __doc__를 출력하면 됩니다.
모듈.__doc__
패키지.__doc__
[ 연습문제 ]
실행 결과
:memmory:
[ 연습문제 ]
표준 입력으로 정수가 입력됩니다. 주어진 calcpkg 패키지를 활용하여 입력된 정수의 제곱근과 입력된 정수를 반지름으로 하는 원의 넓이가 출력되게 만드세요. 제곱근은 calcpkg 패키지에서 operation 모듈의 squareroot 함수를 사용하고, 원의 넓이는 calcpkg 패키지에서 geometry 모듈의 circle_area 함수를 사용하세요(calcpkg 패키지를 사용하지 않고 계산하면 결과가 맞더라도 틀린 것으로 처리됩니다. 반드시 calcpkg 패키지를 사용하세요).
calcpkg/__init__.py
# 내용이 비어 있음
calcpkg/operation.py
import math
def squareroot(n):
return math.sqrt(n)
calcpkg/geometry.py
import math
def circle_area(radius):
return radius * radius * math.pi
judge_package.py
from calpkg.operation import squareroot
from calpkg.geometry import circle_area
a = int(input())
print(squareroot(a))
print(circle_area(a))
표준 입력
2
표준 출력
1.4142135623730951
12.566370614359172
댓글