[Python] 컴퓨터는 모듈을 어떻게 검색할까?

이승연·2020년 11월 25일
1

Python

목록 보기
1/6
post-thumbnail

일단 모듈이 뭐지?

Class: 어떠한 개념을 정의해놓은 것. 속성과 메서드가 있는데 간단히 말해 속성은 개념의 인적사항, 메서드는 개념이 할 수 있는 일들이라고 생각하면 된다.우리가 자주 쓰는 .append() 도 어떠한 클래스의 메서드일 뿐! 어떤 착한 개발자님께서 만들어놓은 것을 우리는 감사하게 쓰고 있는 것이다.
Module:변수, 함수, 클래스를 모아놓은 파일
Package: module을 모아놓은 파일 (파이썬 파일 여러개가 모여있는 파일!)

클래스, 모듈, 패키지를 불러오는 방법

Basic. 기본적으로 import <모듈 이름>을 활용한다. 그 후, 모듈에 들어간 변수, 함수, 또는 클래스를 사용하기 위해서는 <모듈 이름>.<모듈에서 사용하길 원하는 변수/함수/클래스 이름>을 입력. 여기에서 .마침표 앞에 모듈 이름을 명시해주어야만 파이썬이 해당 변수/함수/클래스를 올바른 모듈 내에서 찾을 수 있다. 이 구조를 "name space"라고 한다.

Advanced1. 응용해보자! 모듈과 함수/변수/클래스를 한번에 불러오는 것이다:
from <모듈 이름> import <함수/변수/클래스1>, <함수/변수/클래스2>, <함수/변수/클래스3>...
한 모듈의 모든 요소를 불러오고 싶다면:
from <모듈 이름> import *

Advanced2. *을 사용하는 것의 치명적인 단점이 있다면 지역변수에서 정의한 다른 함수/변수/클래스와 동일한 이름을 가지고 있는 경우 이름 충돌이 일어난다는 것. 이 때문에 import as 명령어를 다음과 같이 쓴다:
import <모듈 이름> as <원하는 이름>
from <모듈 이름> import <함수/변수/클래스1> as <원하는 이름>

A little different for Packages. 패키지도 거의 동일하게 불러오지만 디렉토리를 활용한다는 것이 다른 점이다. 모듈이 모여있는 파일의 디렉토리를 import한다:
import pkg.module1
from pkg.module2 import func2

Using my variables and functions 보통은 그냥 함수나 변수 이름을 쓰면 되는데 내가 여러가지 모듈과 패키지를 가져왔을 경우에는 namespace를 꼭 활용해줘야 하나? 내가 특정 변수나 함수를 가져온 것이 아닌 한 무조건 dot notation을 활용하여 어떤 패키지의 어떤 모듈에서 나온 함수/변수인지를 명시해줘야 하는 듯.

패키지를 쓸 때 알아야 할 점

package import에 있어 초기 설정을 해주어야할 때가 있는데 이때 쓰이는 것이 __init___.py 파일이다. 패키지라는 것을 알려주는 파일이며 패키지가 import될 때 이 파일에 있는 코드들이 자동으로 실행된다!! 일반적으로 세가지를 할 수 있다:

  • import 총 경로 줄여주기: 지금까지는 내가 필요한 변수와 함수의 디렉토리를 dot notation을 사용해서 하나하나 써줘야했는데 이제는 __init___.py 파일에 본 패키지의 어떤 모듈에서 어떤 변수/함수/클래스를 import하겠다라고 명시만 해주면 메인 파일에서의 변수/함수/클래스 활용이 쉬워진다는 뜻. 그럼 메인 파이썬 파일에는 이렇게만 하면 되겠지:
    from .pkg import func2
    func2()
  • Package에서 import할 수 있는 변수/함수/클래스 제한: 기업 내부에서만 사용되어야 하는 코드를 감출 수 있겠지
    - __init_.py 파일에 __all__변수를 정의해주고 노출되어도 괜찮은 변수/함수만 list of strings로 기입해준다. (함수면 () 없어도 된다는 뜻)
  • 그 외 package가 import될 때 꼭 먼저 실행되어야 하는 코드들:

다른 사람의 패키지를 쓸 때에는 PIP라는 파이썬의 package manager역할을 하는 툴을 활용하면 된다:
pip install Django

이제야 본론.

착한 파이썬은 우리가 모듈과 패키지를 찾아달라고 하면 바로 찾아준다. 얘네들은 sys.modules -> built-in modules -> sys.path 순으로 우리가 말한 것을 찾는다.
sys.modules. 단순한 dictionary이며 이미 import된 모듈과 패키지를 저장하고 있다.
built-in modules. 파이썬에서 제공하는 공식 라이브러리!
sys.path. 기본적으로 list of strings이며 각 string 요소는 디렉토리이다. 파이썬은 이 strings를 따른 경로에 가서 우리가 요청한 애들이 있는지 확인한다. 여기까지 봤는데 안나타나면 ModuleNotFoundError를 리턴한다. 내가 pip로 모듈을 다운 받으면 site-packages라는 디렉토리에 설치된다. 그러니까 내가 진짜 다운받았는데 이 에러메세지가 나타나면 거길 찾아보자.

sys는 무엇인가. 파이썬에 포함되어 있는 모듈...

파이썬에서 제공하는 기본 라이브러리와 외부에서 다운받은 애들은 보통 잘 찾아진다. 내가 직접 개발한 local package도 동일하게 잘 찾아지게 하려면 import 경로를 잘 설정해야한다! 여기에는 두가지 방법이 있는데 absolute path와 relative path가 있다. absolute path가 더 길 수는 있지만 직관적이고 혼동의 여지가 적기 때문에 absolute을 더 많이 활용하도록 하자. absolute는 우리가 위에서 한거처럼 쭉쭉쭉 적어주면 된다. 우리가 주소를 대한민국, 인천시, 연수구, 송도문화로 123, 1동 1호라고 하는거랑 똑같음. 전 세계 어디서든 나에게 선물을 보내줄 수 있는 완전한 주소라고 생각하면 돼! 그런데 우리가 지구, 대한민국, 인천시...라고 적어주지는 않잖아. 그거와 똑같이 절대경로도 최상위 파일이름은 안적어준다. 끝!
자...그럼 relative path는 뭐냐..... 내가 지금 있는 위치까지의 경로는 입력해주지 않고 .으로 대체한 다음 나머지를 쭉 써주는 것이다. 우리가 집 근처에 있는 병원에 갈때에는 송도문화로 123, 1동 1호라고만 표기하는 것 처럼! 내가 지금 있는 위치의 상위폴더에서부터 경로를 써줘야할 때에는 ..로 대체한다. .의 수만큼 상위로 이동한다.

1. sys.modules 와 sys.path의 차이점은?
내가 이미 import를 했는지(modules) 안했는지(path)의 차이.

2. sys 도 import 해야하는 모듈입니다. 파이썬은 sys 모듈의 위치를 어떻게 찾을 수 있을까요?
파이썬에서 제공하는 모듈이니... built-in modules에서 찾겠쥐?

3. Absolute path와 relative path의 차이점을 서술해 주세요.
위에 있어용<3

4. calculator 패키지 만들기
앞으로 개발하면서 많은 패키지를 사용할 것이고 만들어야 하는 경우도 있을 수 있기 때문에 이번과제는 직접 패키지를 만들어 보는 과제 입니다.
로컬 환경에서 파이썬을 설치하고 진행해 주세요.
디렉토리 구조는 다음과 같고 각 파일의 코드내용은 다음과 같습니다.
init.py 파일에는 아무코드도 없지만 init 파일은 해당 디렉토리가 패키지임을 알려주는 역할을 합니다.

5. main.py에서 상대경로로 add_and_mutiply 를 임포트 했을 때 발생하는 에러를 확인하고 다음의 파이썬 공식 문서를 참고해서 main module 에서는 패키지의 모듈을 어떻게 임포트 해야하는지 블로깅 해주세요. https://docs.python.org/3/tutorial/modules.html#intra-package-references

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.

  • Python module에는 여러가지의 속성이 있다: __name__, __package__, __doc__, __file__, __dict__ 등... 우리는 여기서 package를 중점적으로 볼 것이다. 더 많은 정보를 원한다면 여기여기로

  • __package__속성은 그 모듈이 위치한 패키지의 경로를 저장한다.

  • __package__속성이 중요한 이유는 상대경로를 이용해서 하나의 모듈을 import할때 그 모듈의 __package__ 속성을 참조하기 때문이다. 그런데 main.py의 경우 __package__는 무조건 None으로 셋팅되기 때문에 파이썬은 main.py의 위치, 정확히 말하면 main.py가 들어있는 package의 위치를 모르겠다며 징징거리는 것이다.

  • 그러니까 main.py에서는 웬만하면 절대경로를 쓰자...

  • 언더바의 종류를 알고 싶다면 [여기로](https://dbader.org/blog/meaning-of-underscores-in-python

  • 이거는 나중에 또 보자.. 지금 수준에서는 확실하게 이해가 안되지만 나중에 import path 에러 해결할 때 좋을 듯

6. add_and_multiply.py에서 multiply함수를 절대경로와 상대경로도 각각 임포트 해보고 main 모듈과 차이점을 생각해보고 결과를 출력해 보세요.


from .multiplication import multiply
from calculator.multiplication import multiply
def add_and_multiply(a,b):
    return multiply(a,b) + (a+b)
  • main함수의 import를 절대경로로 바꾸고 main함수에서 실행을 해야만 맞는 결과가 나온다. 자꾸 add_and_multiply.py에서 실행하면 당연히 에러 메세지가 나온다... 헷갈리지 말기

7. init.py 파일의 역할에 대해서도 정리해서 블로깅 해주세요.
위에 있어용<3

0개의 댓글