Search
Duplicate

Python 프로그래밍 - Package 구조

Created
6/8/2021, 8:21:00 AM
Tags
Empty

Package Import 경로 설정

python 에서는 import를 할 때, sys.path에 등록되어 있는 경로들 중에서, 순서대로 package name을 찾는다. 따라서 만약 같은 이름을 가진 두 개의 package가 있다면 가장 먼저 sys.path에 등록되어 있는 패키지를 가져오게 된다.
아래의 코드를 이용해서 쉽게 path순서를 확인할 수 있따.
import sys print(sys.path)
Plain Text
그리고나서 sys.path.insert( index , path )를 이용해서 내가 import하고자 하는 package의 경로를 넣어주면 원하는 package를 import 할 수 있다.  참고로 sys.path.append(path)의 경우 경로들의 가장 마지막에 추가된다.
sys.path를 relative_path로 추가할 때, 기준이 되는 현재 경로는 다음으로 파악할 수 있다.
import os
os.getcwd()

1. 절대 경로 추가 방식

import sys, os sys.path.append(os.path.abspath('/home/starlab/Webserver/emotion_predict_for_upload')) from main_emotion_predict import emotion_predict
Plain Text
from 패키지명 import 오브젝트이름
이렇게하면 main_emotion_predict.py 파일에서 emotion_predict() 함수를 가져온다.
1-1. 보다 심플한 방법
import sys sys.path.insert(0, '../') import utils
Plain Text
->위의 예제는 바로 자신 위에 parent 폴더에있는 uitls라는 python 파일을 참조한 것임.
2. 상대 경로 참조 방식
아주 심플하고 완전한 상대 경로 참조 방법
sys.path.append(os.path.join(os.getcwd(), "my_lib"))
sys.path.append(os.path.dirname(__file__), "my_lib"))
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
(또는 다음과 같은 방법이 가능한데, __init__을 추가해야할듯)from Aupair.vision import recognize_objects
# from [path] import [function or class]
음.. 이 path가 환경 변수 같은 것에 등록된 path인가보지?? 자동으로 업데이트되는..
Main으로 호출 할 경우 설정
if __name__ == "__main__":# this is used when python is called from putty not other python code.
return ~~
# 파일 참조 시 경로
import os
print os.getcwd() # 이걸 입력해서 현재 호출되는 시점에서의 참조 경로 확인
path = os.path.join('..', '하위 폴더', '폴더 명') # os.path.join을 쓰는 이유는 윈도우/리눅스 호환성을 위해서임.
즉 path = '../폴더명/파일명'  # 이렇게해도 리눅스에서만 쓸거면 문제 없음.

# 문제 해결

ModuleNotFoundError는 무조건 sys.path에서 해당 패키지를 찾을 수가 없을 때 발생한다.
이는 특히 다른 모듈을 하위로 가져오는 submodule이나 subtree를 사용할 때 흔히 발생하는데, 침착하게 sys.path를 잘 설정해주면 해결할 수 있다.

# 순환참조 문제: 원인을 알 수 없는 Import Error

분명히 제대로 __init__도 만들고, 제대로 import를 해줬는데도 불구하고 ImportError: cannot import name '~~~' 에러가나면? 즉 원인을 알 수 없게 ImportError가 나면?

# __init__.py

__init__.py 파일은 해당 디렉토리에 있는 다른 python 패키지나 모듈보다 항상 우선하여 실행된다. 그 역할은 해당 디렉토리의 패키지나 모듈이 필요로하는 initialization 코드를 작성하는 역할이다.
# Submodule Import 하기
module: 1개의 single python file을 의미함.
package: 다른 패키지나 모듈을 담을 수 있는 것.
## 주의사항
1. 순환 참조가 일어나면, "ImportError: cannot import name 'reporter'" 이런 에러가 뜨게된다. 순환 참조를 없앨것https://stackoverflow.com/questions/9252543/importerror-cannot-import-name-x2. 어떤 module의 하위에 있는 특정 함수만 import해도, 해당 module 전체가 import되어진다.(__init__.py에 있는 import가 모두 실행됨. __init__.py 은 모듈이나 패키지의 초기화 코드를 작성하는 용도이다. 해당 모듈/패키지가 import 되는 순간 실행된다.)directory 마다 __init__.py 라는 비어있는 파일을 생성해주면, 해당 디렉토리를 module로써 바로 import 할 수 있다. 즉 __init__이 있어야만 단순 directory가 아니라 package로 인식된다.
그리고 이 __init__.py에서 해당 모듈이 필요로하는 대상을 initialize 코드를 작성해주면 된다.

# Package 만들기

api package를 만들 때, github에 공개된 오픈소스들을 보면 항상 모든 소스코드를 포괄하는 parent package를 갖고 있다. 왜냐하면 이 공통조상이 없으면, 다른 package에서 또 다른 package의 내용을 relative import할 수 없기 때문이다. 만약 공통 조상 package가 없는 상태에서 import를 시도하면 다음과 같은 에러가 발생하고, 이 경우 sys.insert를 이용해서 직접 경로를 추가해야한다. "attempted relative import beyond top-level package"

# Relative import

python에서 package를 relative import할 경우 오직 다음 문법밖에 지원하지 않는다. 즉 "import XXX.YYY.ZZZ"방식은 지원하지않는다
from ..moduleA import foo
Plain Text

# Package와 submodule구조

넘파이 플래튼: 1짜리 디맨젼 날림서치솔티드: 빠른 where. 정렬되었다는 가정하에빠른 where가 필요하면, 그냥 딕셔너리로 미리 인덱스 계산해서 구워두는게빠름딕셔너리.get 하면 키가없을 때 리턴예외를 처리가능함아 그러면 두 아이디를 왔다갔다할 수 있는 맵핑 딕셔너리를 만들어둬야겠다.

Module이나 package 아래에 있는 python 파일 실행하기

아래와 같이 특정 패키지 아래에 있는 python file을 실행시킬 때는 -m 을 붙이고, "." 점을 이용해서 위치를 지정해야 ModuleNotFoundError: No module named 'src'이런 에러를 방지할 수 있다.
TOP