Python - path

Enjoywater·2020년 8월 22일
0

TIL

목록 보기
4/33
post-thumbnail

1. Absolute path / Relative path

파이썬에서는 직접 개발한 local package를 제외한 모듈을 import할 때에는 경로가 크게 문제가 되지 않는다.

  • built-in module -> 내장되어 있어서 잘 찾아진다.
  • pip를 통해 설치한 module / package -> sys.path 속 site-pakages

직접 개발한 local package를 import할 때에는 해당 package의 위치에 맞게 import경로를 잘 선언해야한다.

import하는 경로는 Absolute path / relative path 두 가지가 있다.

Absolute path

Absolute, 절대적인 위치를 기준으로 하는 경로이다.

프로젝트 최상단에서 시작하여 해당 파일의 위치까지의 모든 경로를 나타낸다.


relative path

Relative, 상대적인 위치를 기준으로 하는 경로이다.

import하는 지점을 기준으로 일부의 경로만 나타낸다.

ex) 경로 예시

└── my_app
    ├── main.py
    ├── package1
    │   ├── module1.py
    │   └── module2.py
    └── package2
        ├── __init__.py
        ├── module3.py
        ├── module4.py
        └── subpackage1
            └── module5.py

Absolute path를 사용해서 package1,2를 import 한다면,

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

# 파이썬에서는 dot(.)를 사용해서 경로를 표현한다
#  1개 (.)    import가 선언되는 파일의 현재 위치
#  2개 (..)   상위 디렉토리로 이동하는 경로

처럼 표현이 될 수 있으며,
경로들의 시작점이 전부 "my_app" 프로젝트의 최상단에서 시작하는것을 볼 수 있다.

이 경로는 어느 위치에서 사용하던 변하지 않는다.

참고로 current directory 라고 하는 현재의 프로젝트 디렉토리는 
default로 sys.path 에 포함된다.
그러므로 Absolute path는 current directory 로 부터 경로를 시작한다.

일반적으로 local package를 import 할 때 사용하지만, 경로가 길어질 수 있다는 단점이 있다.
이러한 단점을 보완하기위해 Relative path가 사용할 수 있다.



package2의 module3에 있다고 가정하고, Relative path를 사용해서
package2의 class1을 import하면

from . import class1

package2의 하위 package인 subpackage1의 module5의 function2 함수를 import하면

from .subpackage1.module5 import function2

처럼 표현이 될 수 있다.

경로의 길이가 줄어든다는 장점이 있지만, 쉽게 틀릴 수가 있다.
또한 파일의 위치가 변경되면 경로도 변경되어야 한다.

웬만한 경우 Absolute path를 사용하는게 권장 !



2. path 예제

.
│─── calculator
│    ├── __init__.py
│    ├── add_and_multiply.py
│    └── multiplication.py
└─── main.py

# .pyc파일은 같은 파일명의 .py파일이 다른 곳에서 import되면 생성된다.

위와같은 구조를 가진 폴더 및 파일이 있다.

  • main.py
# absoulte path
from calculator.add_and_multiply import add_and_multiply 

if __name__ == '__main__':
    print(add_and_multiply(1,2))
    
# 정상작동

main.py에서 add_and_multiply에 있는 함수를 사용하는 코드이다.
어떠한 위치에 있어도 사용이 가능한 절대경로를 사용해서 정상적으로 작동시켰다.

하지만 해당 경로를 상대경로로 변경하게되면 에러가 발생한다.

# relative path
from .calculator.add_and_multiply import add_and_multiply

if __name__ == '__main__':
    print(add_and_multiply(1,2))
    
# ValueError: Attempted relative import in non-package

에러의 발생 원인은 if문에 있는 조건식 때문이다.

if __name__ == "__main__":

해당 조건식은 namespace라는 개념을 알고 있어야 이해가 가능하다.
간단히 설명하자면, 각 모듈은 자신만의 namespace를 갖게 된다.

보통 namespace의 이름은 모듈의 파일명과 같다.
때문에 동일한 모듈 내에서 동일한 이름의 클래스나 함수를 정의할 수 없으며,
모듈은 각각 독립적이어서 두 모듈에서는 동일한 이름을 갖는 클래스나 함수를 정의할 수 있다.
namespace 참고

import sys

sys.path

['', 'C:\\Python34\\Lib\\idlelib', 'C:\\Windows\\system32\\python34.zip', 
'C:\\Python34\\DLLs', 'C:\\Python34\\lib', 'C:\\Python34', 
'C:\\Python34\\lib\\site-packages']

-----------------------------------

from sys import path

path

['', 'C:\\Python34\\Lib\\idlelib', 'C:\\Windows\\system32\\python34.zip', 
'C:\\Python34\\DLLs', 'C:\\Python34\\lib', 'C:\\Python34', 
'C:\\Python34\\lib\\site-packages']

# sys  -> 모듈 이름
# path -> sys 모듈의 namespace에 담겨있는 name

위 sys 경로코드는 import의 경우에 namespace가 처리되는 경우이다.
하지만 파이썬 인터프리터가 최초로 파일을 읽어서 실행하는 경우에는 실행 전에 특정한 변수값을 설정한다.
그 중에 하나가
__name__ 변수를 __main__으로 설정하는 것이다.

이미지 속에 있는 각각의 파일에서

print(__name__)

코드를 실행시켜 보면

로 나타난다.

main.py에서 실행시킨 결과값이기 때문에
main.py를 제외한 나머지 파일에서는 파일명으로 지정되었다.

main.py => 프로그램의 시작점 파일에서는 namespace__main__
으로 지정되어 실행이 되기 때문에 절대경로 밖에 사용할 수가 없게된다.


  • add_and_multiply
#absolut path
from .multiplication import multiply

def add_and_multiply(a,b):
    print(__name__)
    return multiply(a,b) + (a+b)
    
#relative path
from calculator.multiplication import multiply
def add_and_multiply(a,b):
    print(__name__)
    return multiply(a,b) + (a+b)

이와는 다르게, 시작점이 아닌 파일에서는 절대경로와 상대경로 모두 정상적으로 작동하게 된다.

profile
블로그 이전 👉🏻 enjoywater.tistory.com

0개의 댓글