TIL25 - SYS

Kiyong Lee·2021년 9월 5일
0

Python from wecode

목록 보기
5/6

Sys

사실 소문자로 'sys'라고 써야함

import abc

라고 하면 abc라는 모듈 혹은 패키지를 import 하겠다는 뜻이다.

그러면 모듈/패키지를 어떻게 찾을 수 있을까?

파이썬은 다음 3가지 장소를 순서대로 보면서 찾는다.

1. sys.modules
2. built-in modules
3. sys.path


sys.modules

파이썬이 모듈이나 패키지를 찾기 위해 가장 먼저 확인하는 곳이다.

단순한 dictionary로, 이미 import된 모듈/패키지를 저장하고 있다.

한 번 import된 모듈과 패키지들은 파이썬에서 다시 찾지 않아도 되도록 하기 때문에,

새로 import 하는 모듈은 sys.modules에서 찾을 수 없다.


built-in modules

파이썬에서 제공하는 파이썬 공식 라이브러리이다.

Built-in 모듈들은 이미 파이썬에 포함되어 나오므로, 파이썬이 쉽게 찾을 수 있다.


sys.path

가장 마지막으로 보는 장소이다.

기본적으로 list이며 string요소들을 가지고 있음

list 경로 하나하나 확인하면서, 해당 경로에 import 하고자하는 패키지의 위치가 있는 지 확인

★ 정 리 하 자 면
파이썬은 import 하고자 하는 모듈과 패키지를 찾을 때
sys.modules -> built-in modules -> sys.path 경로순으로 찾는다.
3단계를 거쳤는데 없다면 ModileNotFoundError 를 리턴한다.


sys 모듈은 어디서 찾지?

import sys를 하고 3가지 위치를 순차적으로 탐색하는 건 알겠는데,

근본적으로 'sys'라는 모듈 자체의 위치를 찾고 싶을 땐 어떻게 해야 할까?

역시 하나하나 찍어보는 게 최고다!

Absolute Path & Relative Path

built-in module과 pip를 통해 설치한 외부 모듈 및 패키지는 import에 큰문제가 되지 않는다

다만, 직접 개발한 로컬 패키지가 문제가 된다.

왜냐하면 위치에 맞게 경로를 잘 입력해야 하기 때문이다.

이렇게 로컬패키지를 import 할 때, 'absolute path' 와 'relative path'로 나뉜다.


Absolute Path

말 그대로 절대적인 경로라는 뜻이다.

import 하는 파일이나 경로에 상관없이 항상 경로가 동일하기 때문이다.

my_app 이라는 프로젝트에 패키지가 1/2로 나누어져 있다.

그리고 패키지2안에는 또다른 서브패키지를 가지고 있다.

이걸 중첩패키지라고 한다.

Absolute Path를 이용해 package1 / package2를 import 한다면

from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1 import module5

이미 my_app 이라는 프로젝트 안에 있기 때문에 'my_app'은 생략한다.

my_app 내에서는 경로가 항상 위와 같이 동일하므로 절대적인 경로라고 부르게 되는 것이다.

그래서 일반적인 로컬 패키지(우리가 직접 개발한)들은 absolute path를 사용하면 된다.

대신 패키지안에 패키지안에.. 이런식으로 가면 경로가 길어진다는 단점이 있는데,

이걸 보완하기 위해 relative path를 사용한다.


Relative Path

프로젝트 최상단을 기준으로 하는 절대 경로의 방법이 아닌, import 위치를 기준으로 정의한다.

그래서 로컬 패키지안에 다른 로컬 패키지를 import할 때 사용한다.

예를 들어, 아까 그림을 다시 가져와서 이야기 해보자면

'package2'의 'module3'에서
'package2'의 'class1'과
'package2'의 하위 패키지인 'subpackage1'의 'module5'의 'function2' 함수를
import하려고 한다면 다음처럼 할 수 있다.

from . import class1
from .subpackage1.module5 import function2

dot('.')은 현재 위치를 뜻한다.
현재 위치는 package2.module3이므로 현재 위치에서부터 원하는 모듈의 경로만 선언해주면 된다.

만약 '..'을 하게 되면 상위 디렉토리를 뜻하는데, relative path는 길이를 줄여주는 근본적인 장점이 있지만,
파일 위치가 변경되면 경로 위치도 변경해줘야 하는점과, 헷갈릴 수 있다는 점에서
절대경로를 사용하는 게 권장된다.


Q(문제라는 뜻)

다음과 같은 구조로 되어 있고, 각 모듈별 코드는 다음과 같다


Q1 : 상대경로로 add_and_multiply 임포트 했을 때 발생하는 에러와, 어떻게 import 해야 할까요?

일단 실행하면 'ImportError' 가 발생하고 부모 패키지 어쩌고..하는 이야기가 나온다.

여기에 어떤 말이 나와 있냐면,

상대 가져오기는 현재 모듈이름을 기반으로 한다
메인 모듈의 이름이 항상 "⎽⎽main⎽⎽"이므로 파이썬 애플리케이션의 메인 모듈로 사용되는
모듈은 항상 절대 가져오기(Absolute Path)를 사용해야 한다.

그렇다. 메인 모듈인 main.py는 절대 가져오기를 사용해야 한다.

그리고 상대 경로를 통해 import를 할 때(기준이 되는 위치를 정할 때),
⎽⎽name⎽⎽ 이라는 속성에 의해 결정된다.
⎽⎽name⎽⎽ == ⎽⎽main⎽⎽ 이라는 속성에서, ⎽⎽main⎽⎽이라는 위치를
파이썬 인터프리터는 알 수 없기 때문에 에러가 발생한다.

⎽⎽name⎽⎽==⎽⎽main⎽⎽ 은 추후에 포스팅 할 예정임
지금은 그렇구나라고 알아두자!


Q2 : add_and_multiple.py에서 multiple함수를 절대/상대경로로 import해보고 main 모듈과 차이점을 생각해보세요

일단 결론적으로 말하면 둘다 값이 잘 출력된다.


위의 문제와 연관됐는데, main.py에서 절대 경로로 import하지
그 외는 상대/절대 상관없기 때문이다.


번외 : init.py ?

init.py라는 파일을 만들었으나, 아무것도 작성하지 않았다.

클래서에서 생각을 해보면 init은 생성자역할을 해서 값을 지정해줄 때 사용하였는데,

패키지에서는 어떤 역할을 할까?


import 경로 길이 줄여주기

위 구조를 가진 파일이 있다.

mod1.py에는 func2 라는 간단한 함수를 만들었고, 이걸 내가 main에서 import 하려면
'from pkg.mod1 import func2'라고 써야 한다.

그런데 init.py에 import 해주면 경로가 줄어든다.

init에서 pkg-mod1까지 기본적으로 import를 해놔서 pkg라고 from에 써줘도 되는 것이다.


import 할 수 있는 변수/함수/클래스 제한

모듈의 특정 함수는 내부적으로만 사용되어야 할 때, ⎽⎽all⎽⎽ 이라는 변수를 쓴다.

기본값은 당연히 뜻 그대로 전체 함수/변수/클래스이다.

그러므로 ⎽⎽all⎽⎽ 변수를 따로 정의해줌으로써, import 될 수 있는 요소들을 제한할 수 있다.

⎽⎽all⎽⎽변수는 string 타입의 list이며, 원하는 요소만 넣어주면 된다.

기존 양식에서 mod2.py만 새로 추가하였고, 안에 func3/func4 함수를 선언하였다.

init 파일에는 func2/3/4를 import했으나, 2와 3만 all에 선언했다.

함수 선언하고, import 했음에도 all에 넣지 않아서 func4는 정의되지 않았다고 나온다.

profile
ISTJ인 K-개발자

0개의 댓글