모듈 : 변수나 함수, 클래스 등을 모아놓은 .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()
import
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 될 수 없음.
pip
)pip
: 파이썬의 package manager
파이썬 설치시 같이 설치되며
pip install Django
import
의 작동원리Import Search 순서
1. sys.modules
2. built-in modules
3. sys.path
sys.modules
built-in modules
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
에러를 리턴한다.
built-in 모듈
과 pip
으로 설치한 외부 모듈은 import에 크게 문제없다.
→ site-packages
라는 디렉토리에 설치되고, sys.path
에 이미 경로가 포함되어 있기 때문이다.
직접 개발한 로컬 패키지는 import 경로를 잘 선언해야한다.
import 하는 파일이나 경로에 상관없이 항상 동일한 절대 경로.
프로젝트 최상단 디렉토리를 기준으로 한다.
current directory
경로는 default로 sys.path
에 포함되서 생략 가능
보통 local package를 import할때 주로 사용한다.
경로의 길이는 길지만 명확하게 경로를 보여준다.
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가 선언되는 파일의 현재 위치를 나타내고, ..
두 개는 상위 디렉토리
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
에러가 나온다.
인터프리터에서 파일자체를 직접 실행
-> 직접 실행되는 파일에서 __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