11. 모듈

10장 함수에서는 프로그램 안의 코드를 재사용하는 방법을 살펴봤습니다. 그렇다면 여러 함수를 한 번에 불러 재사용할 방법은 없을까요? 이럴 때 필요한 것이 바로 모듈입니다.

모듈 작성에는 여러 가지 방법이 있습니다. 가장 간단한 방법은 .py 확장자를 가진 파일을 하나 만들고 여기에 함수와 변수를 한 번에 정의하는 것입니다.

모듈을 작성하는 또 다른 방법은 이렇습니다. 현재 사용 중인 파이썬 인터프리터를 만드는 데 사용되는 프로그래밍 언어로 모듈을 작성하는 것입니다. 예를 들어, 표준 파이썬 인터프리터를 사용 중이라면 C 언어를 이용하여 모듈을 작성하고 컴파일하면 파이썬에서 이 모듈을 불러와 사용할 수 있습니다.

다른 프로그램에서는 import 명령을 통해 모듈을 사용할 수 있습니다. 파이썬 표준 라이브러리 또한 동일한 방법으로 이용 가능합니다. 먼저 표준 라이브러리를 불러와 사용하는 방법을 알아보겠습니다.


https://github.com/swaroopch/byte-of-python/blob/master/programs/module_using_sys.py

import sys

print('The command line arguments are:')
for i in sys.argv:
    print i

print('\n\nThe PYTHONPATH is', sys.path, '\n')
module_using_sys.py(이 코드를 module_using_sys.py로 저장하세요)

실행 결과는 다음과 같습니다.

$ python module_using_sys.py we are arguments
The command line arguments are:
module_using_sys.py
we
are
arguments


The PYTHONPATH is ['/tmp/py',
# many entries here, not shown here
'/Library/Python/2.7/site-packages',
'/usr/local/lib/python2.7/site-packages']


먼저, 표준 라이브러리의 하나인 sys 모듈을 import 문을 통해 불러왔습니다. 이것은 단순히 파이썬에게 이 모듈을 앞으로 사용할 것이라고 알려주는 거라고 보면 됩니다. 여기서 사용된 sys 모듈은 파이썬 인터프리터와 인터프리터가 실행 중인 환경, 즉 시스템system 관련 기능이 담겨 있습니다.

파이썬이 import sys 문을 실행하는 시점에서, 파이썬은 sys 모듈을 찾습니다. 이 경우에는 sys가 내장 모듈이기 때문에 파이썬은 어디서 모듈을 불러와야 하는지 알고 있습니다.

반면, 사용자가 임의로 작성한 모듈의 경우 파이썬 인터프리터는 sys.path 변수에 정의된 디렉토리에 해당 모듈이 있는지 검색합니다. 모듈을 찾으면, 그 모듈 내부에 적혀있는 명령을 읽어들입니다. 그 다음부터 이 모듈을 사용할 수 있게 됩니다. 이러한 초기화 과정은 *모듈을 처음 불러올 때만 일어납니다.

sys 모듈의 argv 변수를 불러올 때에는 sys.argv와 같이 마침표를 통해 접근할 수 있습니다. 이렇게 마침표를 이용함으로써 뒤에 온 이름이 sys 모듈에 존재한다는 것을 명시적으로 알리고, 여러분의 프로그램에 사용될지 모를 argv란 이름의 다른 변수와 충돌이 일어나지 않도록 합니다.

sys.argv 변수는 문자열 리스트입니다 (리스트에 대해서는 12장 자료구조에서 좀 더 자세히 살펴봅니다). 좀 더 구체적으로 sys.argv가 담고 있는 것은 '명령줄 인수' 리스트인데, 이것은 명령줄로부터 프로그램을 실행시킬 때 함께 넘어온 인수를 담고 있습니다.

여러분이 프로그램을 작성하고 실행할 때 IDEIntegrated Development Environment, 통합 개발 환경를 이용하는 경우, IDE 상에서 프로그램을 실행할 때 명령줄 인수를 지정하는 방법에 대해 알아보시기 바랍니다.

여기서는 명령줄에서 직접 python module_using_sys.py we are arguments를 입력해 실행하였습니다. 이것은 python명령을 통해 module_using_sys.py 모듈을 실행시키고 함께 적은 명령줄 인수를 실행될 프로그램에 넘겨준 것입니다. 그러면 파이썬은 sys.argv 변수에 인수를 저장해 주며 프로그램에서 사용이 가능한 상태가 됩니다.

이 때, 여러분이 실행한 스크립트의 이름이 sys.argv 리스트의 첫번째 항목이 됨을 기억하세요. 이 경우 module_using_sys.py가 sys.argv[0]에 해당하며, we는 sys.argv[1] 'are'는 sys.argv[2]에, 'arguments'는 sys.argv[3]에 해당합니다. 파이선은 숫자를 0부터 센다는 점을 기억하세요 (1이 아닙니다!).

sys.path 변수에는 모듈을 불러올 때 찾게 되는 디렉토리 리스트가 담겨 있습니다. sys.path 변수의 첫 번째 항목이 공백 문자열임을 확인하세요. 공백 문자열은 현재 디렉토리를 의미하는데, 현재 디렉토리 또한 sys.path의 일부임을 의미합니다. 이것은 PYTHONPATH 환경변수의 경우와도 같습니다. 즉, 여러분은 현재 디렉토리에 들어 있는 파이썬 모듈을 불러와 사용할 수 있는 것입니다. 그렇지 않은 경우, sys.path에 지정된 디렉토리의 하나에 해당 모듈이 들어 있어야 합니다.

이때 현재 디렉토리란 프로그램을 실행할 때 위치하고 있는 디렉토리를 말합니다. import os; print os.getcwd()를 실행하여 여러분의 프로그램에서 현재 디렉토리가 어디인지 확인할 수 있습니다.


11.1 바이트 컴파일된 .pyc 파일

모듈을 불러오는 것은 상대적으로 무거운 작업이기 때문에, 파이썬은 약간의 트릭을 사용해서 이 과정을 좀 더 빠르게 수행합니다. 그것은 바로 .pyc의 확장자를 가지는 '바이트 컴파일'된, 일종의 중간 단계의 파일을 만들어 두는 것입니다(4.1 파이썬의 특징에서 인터프리터 환경에 대해 설명했었죠). 이러한 .pyc 파일은 다른 프로그램에서 그 모듈을 다시 필요로 할 때 사용됩니다. 모듈을 읽어들이는 데 필요한 몇가지 선행 작업을 수행하지 않아도 되기 때문에 더 빨리 모듈을 불러옵니다.  이렇게 바이트 컴파일된 파일은 플랫폼에 구애받지도 않습니다.


NOTE

.pyc 파일은 .py 파일이 저장되어 있는 디렉토리에 새롭게 생성됩니다. 파이썬이 이 디렉토리에 쓰기 권한을 가지고 있지 않으면 .pyc 파일은 생성되지 않습니다.



11.2 from …​ import 문

매번 sys.를 입력하지 않고서도 argv 변수를 프로그램에서 곧바로 불러와서 사용할 수도 있습니다. 이런 경우, from sys import argv와 같은 구문을 이용합니다.

하지만 식별자 이름간의 충돌을 피하고 프로그램을 좀 더 읽기 쉽게 작성하려면, 이렇게 사용하는 것을 피하고import 문을 사용하기 바랍니다.

from math import sqrt
print "Square root of 16 is", sqrt(16)


11.3 모듈의 name 속성

모든 모듈은 이름을 갖고 있으며, 모듈 내에 포함된 명령을 통해 모듈의 이름을 알아낼 수 있습니다. 이 속성은 현재 모듈이 불러들여져서 사용되고 있는지 아니면 인터프리터에서 곧바로 실행된 것인지를 구문하는 데 유용합니다. 앞서 살펴봤듯 모듈 내부 코드는 모듈이 처음 불러들여졌을 때 실행되게 됩니다. 이러한 속성을 통해 모듈이 외부로부터 불러들여졌을 때와 곧바로 실행되었을 때에 각각 다르게 처리하도록 할 수 있습니다. 그러기 위해서는 name 속성을 사용해야 합니다.


https://github.com/swaroopch/byte-of-python/blob/master/programs/module_using_name.py

if __name__ == '__main__':
    print 'This program is being run by itself'
else:
    print 'I am being imported from another module'
module_using_name.py(이 코드를 module_using_name.py로 저장하세요)

실행 결과는 다음과 같습니다.

$ python module_using_name.py
This program is being run by itself

$ python
>>> import module_using_name
I am being imported from another module
>>>


모든 파이썬 모듈은 name 속성을 가지고 있습니다. name 속성의 이름이 'main'이면 모듈이 사용자로부터 직접 실행된 것임을 의미합니다. 따라서 이에 맞는 적절한 처리를 할 수 있습니다.


11.4 새로운 모듈 작성하기

모듈을 작성하는 것은 쉽습니다. 사실은 여러분이 지금까지 해온 것과 다를게 없습니다! 왜냐하면 모든 파이썬 프로그램은 곧 모듈이기 때문입니다. 즉 .py 확장자를 가진 이름으로 저장하기만 하면 됩니다.


https://github.com/swaroopch/byte-of-python/blob/master/programs/mymodule.py

def say_hi():
    print 'Hi, this is mymodule speaking.'

__version__ = '0.1'
mymodule.py(이 코드를 mymodule.py로 저장하세요)


이 예제는 모듈의 예입니다. 보는 바와 같이, 지금까지 작성한 파이썬 프로그램과 다를 게 없습니다. 이제 다른 파이썬 프로그램으로부터 이 모듈을 불러와서 사용하는 방법을 알아보겠습니다.

다음 예제를 실행하기 전에, 앞의 예제 프로그램 파일이 다음 예제 프로그램과 같은 디렉토리에 있거나, sys.path 중 하나에 있어야 불러올 수 있음을 기억하세요.


https://github.com/swaroopch/byte-of-python/blob/master/programs/mymodule_demo.py

import mymodule

mymodule.say_hi()
print 'Version', mymodule.__version__
mymodule_demo.py(이 코드를 mymodule_demo.py로 저장하세요)

실행 결과는 다음과 같습니다.

$ python mymodule_demo.py
Hi, this is mymodule speaking.
Version 0.1


모듈의 구성 요소에 접근할 때에도 마침표를 이용합니다. 파이썬은 같은 일을 하는 데 같은 표기법을 사용합니다. 따라서 뭔가 새로운 일을 하기 위해 새로운 것을 또 배울 필요가 없습니다. 프로그래머는 이런 것이 파이썬 특유의 '파이썬스러운' 느낌을 준다고 말합니다.

다음은 from..import 구문을 사용하는 예제입니다. 이 코드를 mymodule_demo2.py 파일로 저장하세요.


https://github.com/swaroopch/byte-of-python/blob/master/programs/mymodule_demo2.py

from mymodule import say_hi, __version__

say_hi()
print 'Version', __version__
mymodule_demo2.py

 

mymodule_demo2.py를 실행한 결과는 mymodule_demo.py의 결과와 같습니다.

만약 mymodule을 불러올 때 version이라는 이름이 이미 모듈에 선언되어 있다면, 충돌이 일어날 것입니다. 이런 일은 각 모듈의 버전을 이 이름으로 주로 선언하기 때문에 실제로 자주 일어나는 일이기도 합니다. 따라서, 프로그램이 조금 길어지는 한이 있더라도 왠만하면 import 문을 이용하여 프로그램을 작성하기 바랍니다.

다음과 같이 사용할 수도 있습니다:

from mymodule import *


이것은 say_hi와 같이 모듈에 포함된 모든 공개된 이름을 불러옵니다. 그러나 밑줄 2개로 시작하는 version과 같은 이름은 불러오지 않습니다.


CAUTION

가능하면 from mymodule import * 처럼 사용하는 것을 피하시기 바랍니다.


Zen of Python(파이썬 정신)

파이썬의 여러 지향점 중 하나는 "명시적인 것이 암시적인 것보다 낫다(Explicit is better than Implicit)"입니다. 파이썬에서 import this를 실행하여 다른 지향점에 대해 알아보세요. 또한 이 StackOverflow 에서의 토론을 통해 각각의 규칙에 해당하는 예제를 확인해 보시기 바랍니다.



11.5 dir 내장 함수

dir 내장 함수를 이용하여 객체에 정의되어 있는 식별자 목록을 불러올 수 있습니다. 예를 들어, 모듈의 경우 함수와 클래스 및 변수의 식별자 이름이 정의되어 있습니다.

dir() 함수에 모듈 이름을 넘기면, 모듈 안에 선언된 식별자 이름의 리스트를 반환합니다. 아무것도 넘겨주지 않는 경우, 현재 모듈에 선언된 식별자 이름 리스트가 반환됩니다.

$ python
>>> import sys

# sys 모듈 내에 선언된 속성들의 식별자 이름 목록
>>> dir(sys)
['__displayhook__', '__doc__',
'argv', 'builtin_module_names',
'version', 'version_info']
# 실제로는 너무 길어 여기에는 몇 개만 적었음

# 현재 모듈에 선언된 속성들의 식별자 이름 목록
>>> dir()
['__builtins__', '__doc__',
'__name__', '__package__']

# 새로운 변수 'a' 생성
>>> a = 5

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'a']

# 식별자 이름 제거
>>> del a

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']


먼저 dir 함수를 통해 앞서 불러온 sys 모듈의 식별자 정보를 읽어옵니다. 그러면 내부에 포함된 긴 식별자 이름 리스트가 나타날 것입니다.

다음으로, dir 함수를 아무 인수도 넘기지 않고 실행시킵니다. 그러면 기본값으로, 현재 모듈에 선언된 식별자 리스트가 나타납니다. 이때 앞서 불러온 모듈의 이름도 이 리스트에 포함되어 있음을 확인하세요.

이제 dir이 잘 작동하는지 확인하기 위해, 새로운 변수 a를 선언하고 값을 할당한 뒤 dir 함수를 실행시켜 반환되는 리스트에 새로 생성한 변수가 있는지 확인합니다. del 문을 이용하여 현재 모듈에 선언된 변수 혹은 속성을 제거하면 dir 함수의 출력에 그 결과가 반영됩니다.

del 문은 변수 혹은 이름을 '삭제delete'하는데 사용되며, 이 구문이 실행된 이후에는, 즉 앞의 예제에서는 del a를 실행한 후에는 더 이상 변수 a에 접근할 수 없습니다. 마치 처음부터 이러한 변수가 존재하지 않았던 것처럼요.

dir() 함수는 어떤 객체에도 사용될 수 있습니다. 예를 들어, dir(str)를 실행하면 str 클래스의 속성에 대해 확인할 수 있습니다.

파이썬에는 정의된 속성과 그 값을 읽어오는 데 사용될 수 있는 vars() 함수도 있지만, 이 함수는 모든 경우에서 동작하지는 않습니다.


11.6 패키지

이로써 파이썬 프로그램의 계층 구조에 대해 어느 정도 파악이 됐을 것입니다. 변수는 함수 내부에 존재하며, 함수와 전역 변수는 모듈 안에 존재합니다. 그렇다면 모듈은 어디에 포함될까요? 파이썬에서는 패키지라는 단위가 여기에 해당됩니다.

패키지란 그냥 단순한 폴더입니다. 파이썬에게 이 폴더는 파이썬 모듈을 담고 있다는 것을 알려주는 역할을 하는 init.py라는 특별한 파일을 1개 포함하고 있습니다.

여러분이 'asia', 'africa’라는 하위 패키지를 포함하고 있는 'world'라는 패키지를 만들고 싶다고 가정해 봅시다. 각각의 하위 패키지는 'india', 'madagascar' 등의 하위 패키지를 하나씩 더 갖고 있습니다.

이 경우, 다음과 같이 폴더 구조를 만들면 됩니다.

- <some folder present in the sys.path>/
    - world/
        - __init__.py
        - asia/
            - __init__.py
            - india/
                - __init__.py
                - foo.py
        - africa/
            - __init__.py
            - madagascar/
                - __init__.py
                - bar.py


패키지는 모듈을 계층적으로 관리할 수 있도록 편의상 구성하는 것입니다. 표준 라이브러리에서 이러한 계층 구조를 많이 확인할 수 있습니다.


11.7 요약

함수가 재사용 가능한 프로그램의 한 부분인 것과 같이 모듈은 재사용 가능한 프로그램을 말하며, 패키지는 모듈을 구성하는 계층 구조를 말합니다. 파이썬과 함께 설치되는 표준 라이브러리는 이러한 패키지와 모듈로 이루어진 한 예제입니다.

지금까지 모듈을 사용하고 작성하는 방법에 대해 알아보았습니다. 다음으로, 자료 구조라고 불리우는 개념에 대해 알아봅니다.