파이썬에서 모듈 및 패키지 가져오기

PythonBeginner
지금 연습하기

소개

본 실습에서는 모듈 (module) 과 패키지 (package) 를 사용하여 Python 에서 코드를 구성하고 재사용하는 기본 사항을 학습합니다. 먼저 Python 모듈이 무엇인지, 그리고 모듈이 직접 실행될 때와 가져와서 (imported) 사용될 때 실행 동작이 어떻게 달라지는지 이해하는 것부터 시작하겠습니다.

그런 다음, 모듈의 코드를 프로그램으로 가져오는 두 가지 주요 방법, 즉 전체 모듈을 로드하기 위한 import 문과 특정 함수나 변수를 로드하기 위한 from...import 문을 연습하게 됩니다. 마지막으로, 관련 모듈들을 패키지로 구성하여 잘 정리되고 확장 가능한 프로젝트를 만드는 방법을 배웁니다. 모든 코딩 작업은 WebIDE 내에서 Python 파일과 터미널을 사용하여 진행됩니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 94%입니다.학습자들로부터 97%의 긍정적인 리뷰율을 받았습니다.

파이썬 모듈 이해하기

Python 에서 모듈 (module) 이란 단순히 .py 확장자를 가진 Python 코드 파일을 의미합니다. 모듈을 사용하면 코드를 논리적으로 구성할 수 있어 관리와 재사용이 용이해집니다. 모듈 내에 정의된 함수, 클래스, 변수 등을 다른 스크립트에서 사용할 수 있습니다.

WebIDE 의 왼쪽에는 파일 탐색기 (file explorer) 가 보일 것입니다. 실습 환경에서는 이미 ~/project 디렉토리에 hello.py라는 파일이 생성되어 있습니다.

먼저 hello.py 파일을 열어 내용을 확인해 보세요. 다음과 같은 코드가 포함되어 있어야 합니다.

print("This code runs on import or direct execution.")

if __name__ == "__main__":
    print("This code runs ONLY when the script is executed directly.")

if __name__ == "__main__": 블록은 Python 의 특별한 구문입니다. __name__ 변수는 현재 모듈의 이름으로 평가되는 내장 변수입니다. Python 스크립트가 명령줄에서 직접 실행될 때, 해당 스크립트의 __name__은 문자열 "__main__"으로 설정됩니다. 이 if 문을 사용하면 파일이 다른 모듈에 의해 가져와질 (imported) 때가 아니라, 메인 프로그램으로 실행될 때만 특정 코드가 실행되도록 작성할 수 있습니다.

이것이 실제로 어떻게 작동하는지 확인해 봅시다. WebIDE 에서 터미널을 열고 hello.py 스크립트를 직접 실행해 보세요.

python3 hello.py

print 문이 모두 실행되므로 다음과 같은 출력을 보게 될 것입니다.

This code runs on import or direct execution.
This code runs ONLY when the script is executed directly.

이는 스크립트가 메인 프로그램으로 실행될 때의 동작을 보여줍니다. 다음 단계에서는 이 파일을 모듈로 가져올 때 어떤 일이 발생하는지 살펴보겠습니다.

import 문을 사용한 모듈 가져오기

모듈을 사용하는 가장 일반적인 방법은 import 문을 사용하는 것입니다. 이렇게 하면 모듈 내의 모든 코드가 현재 스크립트에서 사용 가능해집니다.

파일 탐색기에서 main.py라는 빈 파일을 찾을 수 있습니다. 이 파일이 나머지 실습 동안 사용할 메인 스크립트가 될 것입니다.

main.py를 열고 hello 모듈을 가져오기 위해 다음 줄을 추가하세요.

import hello

print("The main.py script has finished.")

파일을 저장합니다. 이제 터미널에서 main.py를 실행합니다.

python3 main.py

출력을 주의 깊게 관찰하세요.

This code runs on import or direct execution.
The main.py script has finished.

hello.py의 첫 번째 print 문만 실행되었음을 알 수 있습니다. if __name__ == "__main__": 블록 안의 코드는 건너뛰어졌습니다. 이는 main.pyhello를 가져올 때, hello.py 컨텍스트 내의 __name__ 변수가 "__main__"이 아닌 모듈 이름인 "hello"로 설정되기 때문입니다. 이 기능은 가져올 때 원치 않는 부수 효과 (side effects) 를 발생시키지 않는 재사용 가능한 모듈을 만드는 데 필수적입니다.

이제 단순히 print 문만 포함하는 것이 아닌, 더 많은 내용을 담고 있는 모듈을 다뤄보겠습니다. module_a.py 파일을 여세요. 이 파일에는 변수, 함수, 클래스가 포함되어 있습니다.

PI = 3.14159

def greet(name):
 print(f"Hello, {name} from module_a!")

class Calculator:
    def add(self, x, y):
        return x + y

main.py를 수정하여 module_a를 가져오고 그 구성 요소들을 사용해 봅시다. 가져온 모듈의 구성 요소에 접근하려면 모듈이름.구성요소이름(module_name.member_name) 구문을 사용합니다.

main.py의 내용을 다음으로 대체하세요.

import module_a

## Access the PI variable
print(f"The value of PI is {module_a.PI}")

## Call the greet function
module_a.greet("LabEx")

## Create an instance of the Calculator class and use its method
calc = module_a.Calculator()
result = calc.add(5, 3)
print(f"5 + 3 = {result}")

파일을 저장하고 실행합니다.

python3 main.py

출력 결과는 다음과 같습니다.

The value of PI is 3.14159
Hello, LabEx from module_a!
5 + 3 = 8

이는 import 문이 전체 모듈을 로드하는 방법과, 모듈 이름을 접두사로 사용하여 해당 모듈의 내용에 접근하는 방법을 보여줍니다.

from...import 를 사용한 특정 객체 가져오기

때로는 모듈에서 특정 항목 몇 가지만 필요할 수 있습니다. from...import 문을 사용하면 특정 함수, 클래스 또는 변수를 현재 스크립트의 네임스페이스 (namespace) 로 직접 가져올 수 있습니다. 이는 모듈이름. 접두사 없이 해당 항목들을 사용할 수 있음을 의미합니다.

이 가져오기 방법을 사용하도록 main.py를 수정해 보겠습니다. module_a 전체를 가져오는 대신, PI 변수와 greet 함수만 가져올 것입니다.

main.py를 다음 코드로 업데이트하세요.

from module_a import PI, greet

## Access PI and greet directly without the module prefix
print(f"The value of PI is {PI}")
greet("World")

파일을 저장하고 터미널에서 실행합니다.

python3 main.py

출력 결과는 다음과 같습니다.

The value of PI is 3.14159
Hello, World from module_a!

보시다시피 PIgreet가 직접 사용되었습니다. 하지만, 만약 Calculator 클래스처럼 가져오지 않은 항목에 접근하려고 하면 오류가 발생합니다.

지금 시도해 보세요. main.py 끝에 다음 두 줄을 추가합니다.

calc = Calculator()
print(calc.add(10, 20))

스크립트를 다시 실행합니다.

python3 main.py

이번에는 스크립트가 NameError와 함께 실패합니다.

The value of PI is 3.14159
Hello, World from module_a!
Traceback (most recent call last):
  File "/home/labex/project/main.py", line 7, in <module>
    calc = Calculator()
NameError: name 'Calculator' is not defined

이 오류는 from...import 문에 지정된 객체만 현재 네임스페이스로 가져와진다는 것을 확인시켜 줍니다. 이 방법은 코드를 더 읽기 쉽게 만들 수 있지만, 서로 다른 모듈에서 동일한 이름의 객체를 가져올 경우 이름 충돌 (naming conflicts) 의 위험을 증가시킬 수 있습니다.

다음 단계로 넘어가기 전에, 오류를 발생시킨 두 줄을 main.py에서 삭제하세요.

Python 패키지 이해 및 사용

프로젝트가 커짐에 따라 관련 모듈들을 단일 디렉토리 계층 구조로 구성하고 싶을 수 있습니다. 이것이 바로 패키지 (package) 의 용도입니다. 패키지는 __init__.py라는 특수 파일을 포함하는 디렉토리입니다 (이 파일은 비어 있을 수 있습니다). 이 파일의 존재는 파이썬에게 해당 디렉토리를 패키지로 취급하도록 지시합니다.

module_a를 포함할 패키지를 생성해 보겠습니다.

먼저, ~/project 디렉토리에 my_package라는 새 디렉토리를 생성합니다. 파일 탐색기에서 마우스 오른쪽 버튼을 클릭하고 "새 폴더 (New Folder)"를 선택하여 이 작업을 수행할 수 있습니다.

mkdir my_package

다음으로, 새로 만든 my_package 디렉토리 안에 필수적인 __init__.py 파일을 생성합니다.

touch my_package/__init__.py

이제 module_a.pymy_package 디렉토리 안으로 이동시킵니다. 파일 탐색기에서 파일을 드래그 앤 드롭할 수 있습니다.

mv module_a.py my_package/

이제 프로젝트 구조는 다음과 같아야 합니다.

~/project/
├── main.py
├── hello.py
└── my_package/
    ├── __init__.py
    └── module_a.py

이러한 패키지 구조가 설정되면, main.py 스크립트에서 module_a를 가져오는 방식을 업데이트해야 합니다. 패키지에서 모듈을 가져오려면 패키지이름.모듈이름(package_name.module_name) 과 같은 점 (dot) 으로 구분된 모듈 이름을 사용합니다.

main.py를 열고 my_package.module_a에서 greet 함수를 가져오도록 수정합니다.

from my_package.module_a import greet

greet("Package")

파일을 저장하고 실행합니다.

python3 main.py

다음과 같은 출력을 보게 될 것입니다.

Hello, Package from module_a!

이는 패키지 내 모듈에서 특정 객체를 가져오는 방법을 보여줍니다. 또는 모듈 자체를 가져올 수도 있습니다.

## Alternative import style
import my_package.module_a

my_package.module_a.greet("Alternative")

패키지는 라이브러리나 프레임워크와 같이 큰 코드베이스를 명확하고 유지보수 가능한 구조로 구성하는 강력한 도구입니다.

요약

본 실습에서는 파이썬 코드 구성의 필수 개념들을 학습했습니다. 재사용 가능한 코드를 작성하기 위한 모듈 (module) 이 무엇인지, 그리고 if __name__ == "__main__": 블록의 목적을 이해하는 것부터 시작했습니다. 이어서 import 모듈이름(import module_name) 구문을 사용하여 모듈을 가져오고 점 표기법 (dot notation) 으로 멤버에 접근하는 방법을 연습했습니다.

더 나아가, from...import 문을 탐색하여 모듈의 특정 객체들을 스크립트의 네임스페이스로 직접 가져오는 방법을 배웠습니다. 마지막으로, __init__.py 파일을 포함하는 디렉토리를 생성하여 관련 모듈들을 패키지 (package) 로 구조화하는 방법과 해당 패키지에서 가져오는 방법을 학습했습니다. 이러한 기술들은 깔끔하고, 체계적이며, 확장 가능한 파이썬 애플리케이션을 작성하는 데 기본이 됩니다.