TIL. 21 - 파이썬 Modules & Packages (import, init, sys, path)
1-1. 모듈, 패키지, PSL
-
모듈 : 변수나 함수, 클래스 등을 모아놓은 .py 파일
-
패키지 : 디렉토리에 특정 기능별로 모듈을 모아둔 것.
패키지는 모듈에 네임스페이스를 제공한다.
-
파이썬 표준 라이브러리 : 기본으로 설치된 내장함수, 모듈, 패키지들을 PSL 이라 부른다.
" 다른 파일에서도 재사용이 가능하게하고,
전체 코드가 너무 커졌을때 여러 파일로 나누어 정리하는 것 "
1-2. 모듈 가져오고 사용하기
모듈 : 변수나 함수, 클래스 등을 모아놓은 .py 파일
패키지 : 디렉토리에 특정 기능별로 모듈을 모아둔 것.
패키지는 모듈에 네임스페이스를 제공한다.
파이썬 표준 라이브러리 : 기본으로 설치된 내장함수, 모듈, 패키지들을 PSL 이라 부른다.
" 다른 파일에서도 재사용이 가능하게하고,
전체 코드가 너무 커졌을때 여러 파일로 나누어 정리하는 것 "
import
-
import 모듈1, 모듈2.함수/변수/클래스
-
사용시
모듈2.함수()
처럼 모듈명을 적어줘야 네임스페이스를 찾을 수 있다.
from ... import ...
-
from 모듈이름 import 함수/변수/클래스1, ... , 함수/변수/클래스N
-
사용시 모듈명이 없어도 바로 호출할 수 있다.
from ... import *
-
해당 모듈의 모든 요소 가져오기
-
local scope를 가진 다른 객체들과 이름 충돌이 일어날 수 있다.
from ... import ... as ...
# as로 새로운 이름을 주어 사용하기 (모듈 이름도 가능)
from my_module import my_func as f1
from my_module2 import my_func as f2
from my_module3 import function_with_name_too_long as f3
f1()
f2()
f3()
- 위의 예시처럼 다른 모듈에 동일한 이름의 함수가 존재할 수도 있고,
모듈이나 다른 요소의 변수명이 너무 길면 줄여줄 수 있다.
1-3. 패키지 가져오고 사용하기
import
- dot notation으로 원하는 모듈을 골라서 가져오면 된다.
import pkg.mod1
from pkg.mod2 import func2
pkg.mod1.func2()
func2()
__init__.py
-
package가 import될때 자동으로 실행된다.
-
__init__.py
파일이 하는 역할
1. Import 할때 경로의 총 길이 줄여주기
2. Package에서 import 할 수 있는 변수/함수/클래스 제한하기
3. 그 외 package가 import될때 꼭 먼저 실행되어야 하는 코드들
4. 위치한 디렉토리가 package임을 알려준다.
1. Import 할때 경로의 총 길이 줄여주기
# main.py
import pkg.mod1
pkg.mod1.func2()
# func2 함수의 경로(패키지, 모듈)를 매번 입력해줘야한다.
__init__
파일에 먼저 import 해준다.
# __init__.py
from .mod1 import func2
# .은 현재 디렉토리를 의미
- 함수의 경로를 줄여준다.
# main.py
from pkg import func2
func2()
2. Package에서 import 할 수 있는 변수/함수/클래스 제한하기
-
__all__
변수 지정하기default 값은 모든 함수/변수/클래스이다.
-> 사용을 원하는 요소들을 string으로 list에 지정한다.
# __init__.py
from .mod1 import func2
from .mod2 import func3
__all__ = ['func2', 'func3'] # 사용하고 싶은 함수 2개 지정
# main.py
from pkg import *
func2()
func3()
func4() ## <== Error.
# func4 함수는 __all__ 에 정의되지 않았으므로 import 될 수 없음.
다른 package 설치하기 (pip
)
-
pip
: 파이썬의 package manager -
파이썬 설치시 같이 설치되며
pip install Django
1-4. import
의 작동원리
-
Import Search 순서
1. sys.modules
2. built-in modules
3. sys.path
1. sys.modules
- 모듈이나 패키지를 찾기위해 가장 먼저 확인하는 곳.
- 이미 import된 모듈과 패키지들을 저장하고 있는 딕셔너리.
- 새로 import하는 경우 sys.modules에서 찾을 수 없다.
2. built-in modules
- 파이썬 공식 라이브러리들
- 이미 파이썬에 포함되어 있다.
3. sys.path
-
경로를 나타내는 string 요소들을 가지고 있는 list
-
만들어지는 과정
-
최초 실행된 py파일의 위치 디렉토리를 추가한다. (interactive shell로 실행하면 '' 빈스트링)
→ 어디서 실행했느냐가 아니라 어디에 위치하느냐.
-
환경 변수의 PYTHONPATH 값을 가져와서 추가한다.
-
OS나 Python 배포판이 설정해 둔 값을 추가한다.
-
['',
'/Users/song-eun-u/anaconda3/bin',
'/Users/song-eun-u/anaconda3/lib/python36.zip',
'/Users/song-eun-u/anaconda3/lib/python3.6',
'/Users/song-eun-u/anaconda3/lib/python3.6/lib-dynload',
'/Users/song-eun-u/anaconda3/lib/python3.6/site-packages',
'/Users/song-eun-u/anaconda3/lib/python3.6/site-packages/aeosa',
'/Users/song-eun-u/anaconda3/lib/python3.6/site-packages/IPython/extensions',
'/Users/song-eun-u/.ipython']
-
sys
는 파이썬이 설치될때 함께 설치되는 라이브러리built-in
모듈이다.→
built-in modules
부분에서 찾을 수 있다. -
sys
모듈을 import 해서sys.modules
와sys.path
를 출력할수도 있고 수정 할 수 있다.
import sys
print(sys.modules) # 이미 import된 것들을 저장
print(sys.path) # 경로들을 나타낸다.
→ sys.path 에서도 못찾으면 ModuleNotFoundError
에러를 리턴한다.
1-5. Absolute Path & Relative Path
-
built-in 모듈
과pip
으로 설치한 외부 모듈은 import에 크게 문제없다.→
site-packages
라는 디렉토리에 설치되고,sys.path
에 이미 경로가 포함되어 있기 때문이다. -
직접 개발한 로컬 패키지는 import 경로를 잘 선언해야한다.
absolute path
-
import 하는 파일이나 경로에 상관없이 항상 동일한 절대 경로.
-
프로젝트 최상단 디렉토리를 기준으로 한다.
current directory
경로는 default로sys.path
에 포함되서 생략 가능 -
보통 local package를 import할때 주로 사용한다.
-
경로의 길이는 길지만 명확하게 경로를 보여준다.
relative path
-
import하는 위치를 기준으로 하는 상대적인 경로
-
local package 안에서 또다른 local package를 import할때 사용한다.
-
경로의 길이를 줄여주지만, 헷갈리기 쉽고 파일 위치가 변경되면 경로도 변경해야한다.
절대 경로, 상대 경로 예시
└── my_app
├── main.py
├── package1
│ ├── module1.py
│ └── module2.py
└── package2
├── __init__.py
├── module3.py
├── module4.py
└── subpackage1
└── module5.py
- 절대경로 -
subpackage1
의module5
의function2
를 import하고 싶을때
# main.py
from package2.subpackage1.module5 import function2
# my_app.package2.subpackage1.module5.py -> 전체 경로 위치
# my_app 디렉토리는 생략 가능
-
상대경로 -
package2
의module3
에서package2
의class1
과subpackage1
의module5
의function2
함수를 Import할때
# package2.module3.py
from . import class1
from .subpackage1.module5 import function2
-> dot .
은 import가 선언되는 파일의 현재 위치를 나타내고, ..
두 개는 상위 디렉토리
1-6. Intra-package References
import로 패키지 가져오기
main.py
에서calculator
패키지의add_and_mulitply
모듈을 import하는 경우
-
절대경로 → 정상 작동
from calculator.add_and_multiply import add_and_multiply
-
상대경로
from .calculator.add_and_multiply import add_and_multiply
→ ImportError: attempted relative import with no known parent package
에러가 나온다.
- 도대체 왜?
파이썬의 스크립트 (파일, 모듈 등)가 실행되는 2가지 방법은
-
인터프리터에서 파일자체를 직접 실행
-> 직접 실행되는 파일에서
__name__
은 무조건__main__
이다. -
다른 파일에서 import 되어서 실행
-> 진정한 의미의 모듈이며
__name__
은해당모듈이름
이다.
메인파일 실행 뒤 상대경로를 통해 다른 모듈을 import 할때,
파이썬은 모듈의 이름(__name__
)에 기반을 두고 현재모듈의 위치를 찾는다.
따라서, 이름이 __main__
으로 바뀐 파일(모듈)은 파이썬이 위치를 찾을 수 가 없다. 상대경로의 출발점이 되는 위치를 못찾아 위와 같은 에러가 발생하는 것이다.
- 결론적으로
__name__
==__main__
이 되는 시작 스크립트 (main.py
)에서는 절대경로 방식으로 import해야한다.
문서 참조
Note that relative imports are based on the name of the current module. Since the name of the main module is always "main" , modules intended for use as the main module of a Python application must always use absolute imports
블로그 참조
https://velog.io/@hamsterhamin/Python-ImportError-attempted-relative-import-with-no-known-parent-package
add_and_multiply.py
에서multiplication
모듈의multiply
함수를 import 하는 경우
-
절대경로 → calculator 패키지를 못 찾는다
from calculator.multiplication import multiply
-
상대경로 → calculator 패키지를 못 찾는다
from calculator.multiplication import multiply
from .multiplication import multiply
로 하면 정상 작동된다.
→ 동일한 디렉토리에 있어서 폴더명을 빼고 상대경로로 작성한다.
- 왜 상대경로로 작성해야 하는가?
메인파일이 실행되고 나면 메인을 기준으로 절대경로가 잡히게 되는데, 이때 add_and_multiply는 경로내에서 calculator 패키지의 하위 모듈로 등록이 된다.
메인모듈의 절대경로가 잡히면서 다른 모듈들을 상대적으로(Relative) 비교할수 있는 뿌리가 생긴 것이다.
- 어떤 파일을 실행하는지에 따라 다르다. (누가
__main__
인지)
main.py 실행시
add_and_multiply를 main모듈에 import할 때 절대경로를 써야한다. (상대경로 쓸 시 에러.)
add_and_multiply에서 multiplication를 import할때 상대경로를 써주어야한다.(절대경로 쓸 시 에러.)
add_and_multiply 직접 실행시 (얘가 메인모듈이 될때)
multiplication를 import할때 절대경로를 써주어야한다.(상대경로 쓸 시 에러.)
여전한 의문점들
sys.path와도 연관이 있는 걸까?
sys.path에 작성된 current directory가 아니어서 그런가?
절대경로를 작성할때 current directory란?
- 참조목록
모듈가져오기 https://wikidocs.net/29
모듈가져오기 https://dojang.io/mod/page/view.php?id=2441
sys.path https://jins-sw.tistory.com/17
sys.path https://sshkim.tistory.com/158
https://docs.python.org/3/tutorial/modules.html
Author And Source
이 문제에 관하여(TIL. 21 - 파이썬 Modules & Packages (import, init, sys, path)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@palza4dev/Modules-Packages-init-sys-path저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)