Python - Modules, Path

solee·2022년 1월 31일
0

Python

목록 보기
3/16

함수란 무엇일까?
재사용이 가능하도록 묶어둔 코드의 집합이다.

그러면 모듈이란 무엇일까?
모듈은 다른 파일에서도 사용할 수 있도록 만든 코드들이 들어있는 "파일" 이다. 함수는 물론이고 변수나 클래스가 들어 있어서 재사용이 용이하도록 하게 한다.

이 모듈이란 이미 우리가 사용하고 있는 것들이기도 하다.
간단하다.
import를 사용하는 모든 것들이 바로 모듈이다! 코드를 처음 배울 때 로또 번호를 만들기 위해 사용하는 random도 모듈이다.


import random
lotto = random.sample(range(1, 46), 6)

말한 김에 random 모듈을 사용하는 예시를 들어 본다면 이렇게 된다. 원하는 범위에서 랜덤으로 숫자를 뽑아 출력하는 기능을 이용하기 위해서는 모듈을 import해야 하는 것이다.

모듈을 불러오면 random.sample()처럼 random.을 이용해 원하는 기능이 random 모듈 내에 있음을 알리고 사용하는 것이다.



sys 모듈

수많은 모듈 중 sys 모듈에 대해 알아보자.
sys 모듈이란:

아마도 읽는 사람: 예?

런타임 환경을 조작하는 함수나 변수? 원래도 다 조작해서 쓰는 거 아닌가? 읽자마자 든 생각이다. 뭘 더 어떻게 조작한다는 건지 모르겠다. 인터프리터와 상호작용하는 변수와 함수에 액세스를 제공하도록 허용한다는데 이것도 뭘 더 어떻게 한다는 건지 모르겠다.

찾아보니 sys 모듈은 stdin이라는 기능을 가지고 있다. 커맨드라인에 직접적으로 명령을 입력할 수 있다고 한다. 그런데 stdin? 아주 잘 아는 건 아니지만 서치하다가 C언어에 관련하여 보았던 것 같다. 검색해 보니 입출력을 담당한다. 또 'standard input device'의 약자기도 하다. 이때 output이 되면 stdout이라고도 하는 모양이다.
그 외에도 sys.exit() 등 수많은 기능들이 있는데, 파이썬 docs 링크를 가져왔으니 더 확인하고 싶다면 여기다.


sys모듈을 먼저 설명하는 이유가 있다. 우리가 모듈들을 import해서 사용할 때, 파이썬은 가장 먼저 sys모듈을 찾는다. 거기서 없으면 built-in모듈들 중에서 찾고, 거기서도 없으면 sys.path에서 찾기 때문이다.
곧, sys모듈은 다른 모듈들의 이름과 경로를 가져올 수 있다!


sys.modules를 먼저 실행시켜 보았다. 너무 길어서 반의 반 정도만 잘라 온 거다.

{'sys': <module 'sys' (built-in)>, 
'builtins': <module 'builtins' (built-in)>, 
'_frozen_importlib': <module 'importlib._bootstrap' (frozen)>, 
'_imp': <module '_imp' (built-in)>, 
'_warnings': <module '_warnings' (built-in)>, 
'_io': <module 'io' (built-in)>, 
'marshal': <module 'marshal' (built-in)>, 
'posix': <module 'posix' (built-in)>,
'_frozen_importlib_external': <module 'importlib._bootstrap_external' (frozen)>,
'_thread': <module '_thread' (built-in)>,
'_weakref': <module '_weakref' (built-in)>,
'time': <module 'time' (built-in)>,
...

sys.modules 명령어는 보이는 바와 같이 딕셔너리 형태로 모듈들의 이름과 속성(빌트인 모듈인지 등...)을 보여준다.
그런데! 맨 앞에 있는 모듈이 보이는가?

'sys': <module 'sys' (built-in)>

그렇다. sys 모듈도 빌트인 모듈인데, 맨 앞에 있기 때문에 파이썬이 모듈을 찾을 때 sys에서 먼저 찾고 그 후에 다른 빌트인 모듈을 탐색하게 되는 것이다.


sys.path는 말 그대로 모듈들의 경로를 보여주는데, 문자열의 리스트이다.

['/opt/virtualenvs/python3/lib/python3.8/site-packages', 
'/usr/lib/python38.zip', 
'/usr/lib/python3.8', 
'/usr/lib/python3.8/lib-dynload']



사용자가 직접 생성한 모듈의 경로 지정

이미 존재하는 모듈을 사용할 수도 있지만, 모듈이나 패키지를 직접 생성하여 사용할 수도 있다. 이 때에는 import할 때에 sys모듈도 빌트인 모듈도 아니고 path에 등록되어 있지도 않으므로 그냥 import할수는 없다.
그러면 어떻게 해야 할까? 파이썬에게 모듈 파일의 위치를 알려 주면 된다.

파일의 위치를 지정하는 두 가지 방법이 있다. "절대 경로"와 "상대 경로"다.


절대 경로

실제 주소라고 생각한다면 다음과 같다.

서울특별시 강남구 강남대로 438 스타플렉스 6층

대한민국 전체를 기준으로 잡고 위치를 설명해 준다.


절대 경로는 패키지를 기준으로 그 위치를 설명하는 것이다. 윈도우 기준으로 폴더에서 주소창처럼 생긴 것을 클릭하면 바로 나타난다.

C:\Users\Administrator\Desktop\PythonWorkspace\user

예를 들면 이런 것이다. C드라이브 안에 Users 폴더 안에 Administrator 폴더 안에... 와 동일하다. 다만 파이썬에서는 /나 \ 대신 .을 쓴다.
아까 random.sample을 쓴 것을 기억하는가? random 모듈 안에 있는 sample이라는 기능을 사용하는 것이다.

VSCode를 이용해 만들어 본 디렉토리 모형이다. 조금 알아보기 어려워 설명하자면, user라는 프로젝트에 packagenewPackage라는 두 디렉토리가 있고, newPackage 안에는 newSubPackage라는 디렉토리가 있는 형태다.

  • user라는 프로젝트에 main.py 파일이 있다.
  • package 디렉토리에는 모듈 1, 2번.
  • newPackage 디렉토리 안에는 __init__.py와 모듈 3, 4번.
  • newSubPackage 디렉토리에는 모듈 5번이 있다.

그러면 절대경로로는 아래와 같이 표현할 수 있다.

from package import module1
from package.module2 import ~~~
from newPackage import ~~~
from newPackage.newSubPackage.module5 import ~~~

package에서 원하는 모듈을 통째로 import할 수 있다. 또는 package.module2의 형태로 모듈까지 같이 import해서 해당 모듈의 클래스나 함수, 변수 등(위의 예시에서는 ~~~으로 표현되었다) 필요한 것만 가져오는 방법이 있다.
신경쓸 점은, 파이썬의 경로가 .을 이용한다는 점과 프로젝트명은 삽입되지 않는다는 점이다. 또 확장자는 입력하지 않는다.


상대 경로

절대의 반대말은 상대다. 절대평가의 반대도 상대다. 그러므로 절대 경로의 반대도 상대 경로일 것이다. 실제 주소를 기준으로 설명한다면 다음과 같다.

두 번째 골목에서 왼쪽으로 꺾어서 세 번째 파란 대문

현재 위치를 기반으로 설명하고 있는 것을 볼 수 있다. 현재 위치가 바뀌면 이 설명이 가리키는 곳도 바뀐다.

이처럼 절대 경로가 프로젝트를 기준으로 설정된다면 상대 경로는 import를 하려는 해당 파일을 기준으로 설정된다.

아까와 같은 예시를 들어 보자.
지금 내가 편집하고 있는 파일이 newPackage에 있는 module3.py라고 하자. 같은 패키지 안에 있는 다른 파일에서 함수 def aa()를 사용하고 싶다. 그러면 이렇게 하면 된다.

from . import aa

.은 현재 위치를 뜻한다. 내가 지금 newPackage에서 작업중이므로 .newPackage까지의 위치를 의미하는 것이다.

newPackage 안에 있는 newSubPackage에서 모듈을 찾게 하려면?

from .newSubPackage.module5 import aa

반대로 newSubPackage 바깥에 있는 패키지에서 모듈을 찾고 싶다면 어떻게 해야 할까? ..을 쓰면 된다. newSubPackage에서 상위 디렉토리로 움직이면 newPackage가 된다는 것을 알아야 한다.

from ..newPackage.module4 import aa



마치며

상대 경로는 더 쉽고 덜 번거로워 보이지만, 혼자 짧게 작업하는 작은 프로젝트에서면 몰라도 여러 사람이 함께 사용하거나 디렉토리가 많은 경우에는 적합하지 않다. 앞서도 언급했듯, 현재 위치가 바뀌면 해당 상대 경로가 설명하는 위치도 바뀌기 때문이다. 디렉토리의 구조를 변경하게 될 때에는 사용한 모듈 하나하나의 경로나 연관되어야 하는 위치를 기억하지 쉽지 않기 때문에 권장되지 않는다고 한다.

그러면 상대 경로는 언제, 왜 쓰라고 만들어 둔 건지 궁금해서 검색해 보니

이런 글을 찾을 수 있었다. 큰 패키지를 수정할 때에 각각의 서브 패키지를 하나하나 수정할 필요가 없기도 하고, 패키지 내부에 있는 모듈은 상대 경로가 더 import하기 쉽다는 것이다. 그러니 두 방식을 다 연습해 가며 적절한 순간에 적절하게 사용할 수 있도록 해야 할 것이다.

profile
DA DA DA

0개의 댓글