9장. 모듈
9장. 모듈
앞에서 함수를 통해 여러분의 프로그램 안에서 코드를 재사용하는 방법에 대해서 배워 보았습니다. 그러면 여러 함수들을 한꺼번에 불러들여 재사용하는 방법은 없을까요? 네, 이럴 때 모듈을이용합니다.
모듈을 작성하는 데에는 여러가지 방법이 있습니다만, 가장 간단한 방법은 .py 확장자를 가진 파일을 하나 만들고 그 안에 함수들과 변수들을 정의해 두는 것입니다.
모듈을 작성하는 또 한 가지 방법은 여러분이 현재 사용중인 파이썬 인터프리터를 만드는데 사용되는 프로그래밍 언어로 모듈을 작성하는 것입니다. 예를 들어, 표준 파이썬 인터프리터를 사용 중인 경우 C 언어 를 이용하여 모듈을 작성하고 컴파일하면 파이썬에서 이것을 불러와 사용할 수 있습니다.
다른 프로그램에서 import 명령을 통해 모듈을 불러와 사용할 수 있습니다. 파이썬 표준 라이브러리 또한 동일한 방법을 통해 이용이 가능합니다. 일단, 표준 라이브러리를 불러와 사용하는 방법을 알아보도록 하겠습니다.
예제 ( module_using_sys.py 로 저장하세요):
1 2 3 4 5 6 7 8 | import sys print('The command line arguments are:') for i in sys.argv: print (i) print ('\n\nThe PYTHONPATH is', sys.path, '\n' ) | cs |
실행 결과
1 2 3 4 5 6 7 8 9 10 | The command line arguments are: module_using_sys.py we are arguments The PYTHONPATH is ['/tmp/py', # many entries here, not shown here 1 http://docs.python.org/2/extending/ '/Library/Python/2.7/site-packages', '/usr/local/lib/python2.7/site-packages'] | cs |
동작 원리먼저, 표준 라이브러리 중 하나인 sys 모듈을 import 문을 통해 불러왔습니다. 이것은 단순히 파이썬에게 이 모듈을 앞으로 사용할 것이라고 알려주는 과정이라고 생각하시면 편합니다. 여기서 사용된 sys 모듈은 파이썬 인터프리터와 인터프리터가 실행중인 환경, 즉 시스템(system)에 관련된 기능들이 담겨 있습니다.
파이썬이 import sys 문을 실행하는 시점에서, 파이썬은 sys 모듈을 찾습니다. 이 경우에는내장 모듈을 불러오는 것이므로, 파이썬이 이미 어디서 이것을 불러와야 하는지 알고 있습니다.
만약 그렇지 않은 경우, 예를 들어 파이썬으로 여러분이 직접 작성한 모듈인 경우 파이썬 인터프리터는 sys.path 변수 에 정의된 디렉토리들에 해당 모듈이 있는지 검색합니다. 그리고 나서 모듈을 찾아내면, 그 모듈 내부에 적혀있는 명령들이 읽어들여지게 되며 그 다음부터 모듈이 사용가능*하게 됩니다. 이러한 초기화 과정은 *첫번째로 모듈을 불러올 때만 이루어진다는 것을 기억하세요.
sys 모듈의 argv 변수를 불러올 때, 마침표를 이용하여 sys.argv 와 같이 접근합니다. 이와같이 마침표를 이용함으로써 뒤에 온 이름이 sys 모듈에 존재한다는 것을 명시적으로 알려 주고, 또한 여러분의 프로그램에 사용될지 모를 argv 라는 이름을 가진 다른 변수와 충돌이 일어나지 않도록 합니다.
sys.argv 변수는 문자열의 리스트 입니다 (리스트에 대해서는 뒤 챕터에서 좀 더 자세히 다룰 것입니다). 좀 더 구체적으로 sys.argv 가 담고 있는 것은 *명령줄 인수*들의 리스트인데, 이것은 명령줄로부터 프로그램을 실행시킬 때 함께 넘어온 인수들을 담고 있는 것입니다. 여러분이 프로그램을 작성하고 실행할 때 IDE(Integrated 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 의 일부임을 의미하며 이것은모듈 75 PYTHONPATH 환경변수의 경우와도 같습니다. 즉, 여러분은 현재 디렉토리에 들어 있는 파이썬 모 듈을 불러와 사용할 수 있는 것입니다. 그렇지 않은 경우, sys.path 에 지정된 디렉토리들 중 하나에 해당 모듈이 들어 있어야 합니다.
이때 현재 디렉토리란 프로그램을 실행할 때 위치하고 있는 디렉토리를 말합니다. import os;print os.getcwd() 를 실행하여 여러분의 프로그램에서 현재 디렉토리가 어디인지 확인할 수 있습니다.
9.1. 바이트 컴파일된 .pyc 파일
모듈을 불러오는 것은 상대적으로 무거운 작업이기 때문에, 파이썬은 약간의 트릭을 사용해서 좀 더 이 과정을 빠르게 수행할 수 있게 합니다. 그것은 바로 .pyc`의 확장자를 가지는 *바이트 컴파일*된, 일종의 중간 단계의 파일을 만들어 두는 것입니다 (입문 섹션에서 파이썬의 인터프리터 환경에 대해 설명했었죠?). 이러한 `.pyc 파일은 다른 프로그램에서 그 모듈을 다시 필요로 할 때 사용되며, 이 경우 모듈을 읽어들이는 데 필요한 몇가지 선행작업을 수행하지 않아도 되게 되어 더 빨리 모듈을 불러올 수 있습니다. 또한, 이렇게 바이트 컴파일된 파일은 플랫폼에 구애받지 않습니다.
.pyc 파일은 .py 파일이 저장되어 있는 디렉토리에 새롭게 생성됩니다. 파이썬이 이 디렉토리에 쓰기 권한을 가지고 있지 못한 경우, .
pyc 파일은 생성되지 않을 것입니다.
9.2. from … import 문
매번 sys. 를 입력하지 않고서도 argv 변수를 프로그램에서 곧바로 불러와서 사용할 수도 있습니다. 이런 경우, from sys import argv 와 같은 구문을 이용합니다.
하지만 식별자 이름간의 충돌을 피하고 프로그램을 좀 더 읽기 쉽게 작성하기 위해서, 가능하면 이렇게 사용하는 경우를 피하고 import 문을 사용하기를 권합니다.
예제
1 2 | from math import sqrt print "Square root of 16 is", sqrt(16) | cs |
9.3. 모듈의 name 속성
모든 모듈은 이름을 갖고 있으며, 모듈 내에 포함된 명령을 통해 모듈의 이름을 알아올 수 있습니다. 이 속성은 현재 모듈이 불러들여져서 사용되고 있는지 아니면 인터프리터에서 곧바로 실행된 것인지를 구문하는데 편리하게 사용될 수 있습니다. 이전에 알아보았지만, 모듈 내부의 코드는 모듈이 첫번째로 불러들여졌을 때 실행되게 됩니다. 이러한 속성을 통해 모듈이 외부로부터 불러들여졌을 때와 곧바로 실행되었을 때에 각각 다르게 처리하도록 할 수 있습니다. 이를 위해 name속성을 사용합니다.
예제 ( module_using_name.py 로 저장하세요)
1 2 3 4 | if __name__ == '__main__': print ('This program is being run by itself') else: print ('I am being imported from another module') | cs |
실행 결과
1 | This program is being run by itself | cs |
동작 원리모든 파이썬 모듈은 name 속성을 가지고 있습니다. 만약 그 이름이 ’main'`일 경우, 이것은 모듈이 사용자로부터 직접 실행된 것임을 의미하며 따라서 이에 맞는 적절한 처리를 해 줄수 있습니다.
9.4. 새로운 모듈 작성하기
모듈을 작성하는 것은 쉽습니다. 사실은 여러분이 지금까지 해 왔던 것과 별 다를게 없습니다! 왜냐하면 모든 파이썬 프로그램은 곧 모듈이기 때문입니다. 즉 .py 확장자를 가진 이름으로 저장되기만 하면 됩니다. 아래 예제를 통해 이에 대해 좀 더 분명하게 알 수 있을 것입니다.
예제 ( mymodule.py 로 저장하세요)
1 2 3 4 | def say_hi(): print ('Hi, this is mymodule speaking.') __version__ = '0.1' | cs |
위 예제는 모듈 예시입니다. 보시는 바와 같이, 지금까지 작성해왔던 파이썬 프로그램들에 비해 별다른 특별한 것이 없습니다. 다음으로는 다른 파이썬 프로그램으로부터 이 모듈을 불러와서 사용하는 방법을 알아보겠습니다.
아래 예제를 실행시키기 전에, 위 예제 프로그램 파일이 아래 예제 프로그램과 같은 디렉토리에 있거나 혹은 sys.path 중 하나에 있어야 제대로 불러올 수 있음을 기억하세요.
모듈 불러오기 예제 ( mymodule_demo.py 로 저장하세요)
1 2 3 4 | import mymodule mymodule.say_hi() print('Version', mymodule.__version__) | cs |
실행 결과
1 2 | Hi, this is mymodule speaking. Version 0.1 | cs |
동작 원리모듈의 구성 요소에 접근하는 데에도 앞서 알아보았던 것과 동일하게 마침표를 이용하여 접근합니다. 파이썬은 같은 일을 하는 데 같은 표기법을 사용합니다. 따라서 뭔가 새로운 일을 하기 위해 새로운 것을 또 배울 필요가 없습니다. 프로그래머들은 이런 것들이 파이썬 특유의 '파이썬스러운' 느낌을 주게 한다고 말합니다.
아래는 from..import 구문을 사용하는 예제입니다 (`mymodule_demo2.py`로 저장하세요):
1 2 3 4 | from mymodule import say_hi, __version__ say_hi() print( 'Version', __version__) | cs |
mymodule_demo2.py 를 실행한 결과는 mymodule_demo.py 의 결과와 같습니다.
1 2 | Hi, this is mymodule speaking. Version 0.1 | cs |
만약 mymodule을 불러올 때 version 이라는 이름이 이미 모듈에 선언되어 있었다면, 충돌이 일어날 것입니다. 사실 이 경우는 각 모듈의 버전을 이 이름으로 주로 선언해 두기 때문에 실제로 자주 일어나는 일이기도 합니다. 따라서, 프로그램이 조금 길어지는 한이 있더라도 왠만하면 import 문을 이용하여 프로그램을 작성하기를 권합니다.
아래와 같이 사용할 수도 있습니다:
1 | from mymodule import * | cs |
이것은 say_hi’와 같이 모듈에 포함된 모든 공개된 이름들을 불러옵니다. 그러나 밑줄 두 개로 시작하는 `version 과 같은 이름들은 불러오지 않습니다.
주의: 가능하면 from mymodule import * 처럼 사용하는 것을 피하시기 바랍니다.
1 2 3 4 5 | Zen of Python (파이썬 정신) 파이썬의 여러 지향점 중 하나는 "명시적인 것이 암시적인 것 보다 낫다 (Explicit is better than Implicit)" 입니다. 파이썬에서 import this 를 실행하여 다른 지향점들에 대해 알아보세요. 또한 이 StackOverflow 에서의 토론2 을 통해 각각의 규칙에 해당하는 예제들을 확인해 보시기 바랍니다. | cs |
9.5. dir 내장 함수
dir 내장 함수를 이용하여 객체에 정의되어 있는 식별자들의 목록을 불러올 수 있습니다. 예를 들어, 모듈의 경우 함수와 클래스 및 변수들의 식별자 이름이 정의되어 있을 것입니다. dir() 함수에 모듈 이름을 넘겨 주면, 모듈 안에 선언된 식별자 이름들의 목록을 반환해 줍니다. 아무것도 넘겨주지 않는 경우, 현재 모듈에 선언된 식별자 이름들의 목록이 반환됩니다.
예제
1 2 3 4 | import sys print ('dir(sys)',dir(sys)) print ('dir()', dir()) | cs |
결과
1 2 | dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_coroutine_wrapper', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'set_coroutine_wrapper', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions', 'winver'] dir() ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'sys'] | cs |
# 새로운 변수 'a' 생성
1 2 3 | a = 5 print ('dir()', dir()) | cs |
1 | dir() ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'sys'] | cs |
# 식별자 이름 제거
1 2 3 4 | a = 5 del a print ('dir()', dir()) | cs |
결과
1 | dir() ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'sys'] | cs |
동작 원리먼저 dir 함수를 통해 앞서 불러온 sys 모듈의 식별자 정보를 읽어옵니다. 그러면 내부에 포함된 긴 식별자 이름 목록이 나타나는 것을 확인할 수 있습니다.
다음으로, dir 함수를 아무 인수도 넘기지 않고 실행시킵니다. 그러면 기본값으로, 현재 모듈에 선언된 식별자 목록이 나타납니다. 이 때 앞서 불러온 모듈의 이름도 이 목록에 포함되어 있음을 확인하세요.
이제 dir 가 잘 작동하는지 확인하기 위해, 새로운 변수 a 를 선언하고 값을 할당해 준 뒤 dir 함수를 실행시켜 반환되는 목록에 새로 생성된 변수가 포함되어 있는지 확인합니다. del 문을 이용하여 현재 모듈에 선언된 변수 혹은 속성을 제거하면 dir 함수의 출력에 그 결과가 반영됨을 또한 알 수 있습니다.
del 문은 변수 혹은 이름을 *삭제(delete)*하는데 사용되며 이 구문이 실행된 이후에는, 즉 위 예제의 경우에는 del a 를 실행한 이후에는, 더 이상 변수 a 에 접근할 수 없습니다. 마치 처음부터 이러한 변수가 존재하지 않았던 것처럼 말입니다.
dir() 함수는 어떤 객체에도 사용될 수 있습니다. 예를 들어, dir(str) 를 실행하면 str 클래스의 속성에 대해서 알아볼 수 있습니다.파이썬에는 정의된 속성과 그 값을 읽어오는 데 사용될 수 있는 vars()3 함수 또한 존재합니다만, 이 함수는 모든 경우에서 동작하지는 않습니다.
9.6. 패키지
지금까지 여러분은 파이썬 프로그램의 계층 구조에 대해 어느정도 파악이 되셨을 것입니다. 변수는 함수 내부에 존재하며, 함수와 전역 변수는 모듈 안에 존재합니다. 그렇다면 모듈은 어디에 포함되는 것일까요? 파이썬에서는 패키지라는 단위가 이에 해당됩니다.
패키지란 그냥 단순한 폴더입니다만, 파이썬에게 이 폴더는 파이썬 모듈을 담고 있다는 것을 알려주는 역할을 하는 init.py 라는 특별한 파일을 한 개 포함하고 있습니다.
여러분이 'asia', 'africa’라는 하위 패키지를 포함하고 있는 'world' 라는 패키지를 만들고 싶다고 가정해 봅시다. 또한 각각의 하위 패키지는 'india', 'madagascar' 등등의 하위 패키지를 하나씩 더 갖고 있습니다.
이 경우, 아래와 같이 폴더 구조를 만들어 주면 됩니다:
- <some folder present in the sys.path>/
패키지는 계층적으로 모듈을 관리할 수 있게 편의상 구성하는 것입니다. 표준 라이브러리에서 이
러한 계층 구조를 많이 확인하실 수 있을 것입니다.
9.7. 요약
함수가 재사용 가능한 프로그램의 한 부분인 것과 같이 모듈은 재사용 가능한 프로그램을 말하며, 패키지는 모듈을 구성하는 계층 구조를 말합니다. 파이썬과 함께 설치되는 표준 라이브러리는 이러한 패키지와 모듈로 이루어진 한 예제입니다.
지금까지 모듈을 사용하고 작성하는 방법에 대해 알아보았습니다.
다음으로, 자료 구조라고 불리우는 개념에 대해 알아보도록 합시다.