(TIL9) Modules & Packages

SooHyung Kim·2020년 4월 1일
0

Today I learned

목록 보기
9/25

Modules & Packages

모듈 : 변수나 함수, 클래스 등을 모아놓은 파일

모듈을 모아놓은 이유
1. 다른 파일에서 재사용이 가능
2. 전체 코드가 한 파일에 넣기에는 너무 커졌을 때 나누어서 정리하기 위함

   my_list = [1, 2, 3, 4, 5]
   my_list_length = len(my_list)

   # len은 파이썬이서 이미 모듈로 구현해놓음
  • 모듈 만들기

    • 재사용 하고 싶은 함수, 클래스, 변수를 구현한 후 파일로 생성 후 import 키워드를 통해 사용

      ## my_module.py
      my_module_var = 7
      
      def my_module_func()
          return 'hello!'
      
      class MyModuleClass:
          pass
  • 모듈 사용하기

    • import 키워드 사용
    ## import my_module
    import my_module				# import 모듈명
    print(my_module.my_module_var()) 		# <모듈명>.<사용 변수/함수/클래스명>
    my_module.my_moudle_func()
    my_module_class = my_module.MyModuleClass()
    • from import 키워드 사용
      • import * 를 해주면 모듈의 모든 요소가 import
    from my_module import my_module_func, my_module_var
    print(my_module_var)
    my_module_func()
    • import as 키워드 (새로운 이름을 지정)
     import my_module as m1
     m1.my_module_func()

패키지 : 모듈보다 더욱 큰 개념으로 디렉토리 개념

  • 일반 모듈처럼 import하여 사용할 수 있으며, dot을 이용하여 해당 패키지의 원하는 모듈을 import해야 함

    import pkg.mod1
    from pkg.mod2 import func2
    
    pkg.mod1.func2()
    func2()
  • Package Initialization

    • package의 import 시 초기 설정을 진행할 때 파이썬에서는 __init__.py 파일을 통해 이를 가능하게 해줌

    • package에 __init__.py 파일이 있을 경우 패키지의 import 시 __init__.py 파일의 코드들이 자동적으로 실행

      __init__.py의 역할

      1. Import 할 때 경로의 총 길이 줄여주기
      2. 패키지에서 import할 수 있는 변수/함수/클래스 제한
      3. 그 외 package가 import될 때 꼭 먼저 실행되어야 하는 코드들
    import pkg.mod1
    pkg.mod1.func2()			# 너무 길기 때문에 줄여보자
    ----------------------------------
    # __init__.py				# ``__init__``.py 파일에 한번 import!
    from mod1 import func2
    
    #main.py
    from pkg import func2
    
    func2()
    • 내부적으로 제한하고 싶은 함수는 외부에서 import 되는 것을 막기 위해 _._all__변수를 따로 지정
      • 기본적으로 패키지를 통해 import될 수 있는 요소들은 모두 _._all__변수를 통해 정의되며, default 값은 모든 함수/변수/클래스임
    # __init__.py
    from mod1 import func2
    from mod2 import func3
    
    __all__ = ['func2', 'func3']
    
    #main.py
    from pkg import func* 	# func는 권장하지 않음
    
    func2()
    func3()
    func4() 		# func4함수는 정의되지 않았으므로 import 될 수가 없음

import search 순서

파이썬에서는 sys.modules ----> built-in modules ----> sys.path 순으로 검색

sys.modules

  • 단순 dictionary 형태이며 이미 import된 모듈과 패키지를 저장하고 있어 한 번 import되면 따로 다시 찾지 않아도 되나, 새로 import하는 모듈, 패키지는 확인이 불가능함

    import sys
    print(sys.modules)
    >>>
    {'sys': <module 'sys' (built-in)>, 
     'builtins': <module 'builtins' (built-in)>, 
     '_frozen_importlib': <module '_frozen_importlib' (frozen)>, 
     '_imp': <module '_imp' (built-in)>, 
     '_warnings': <module '_warnings' (built-in)>,......}

built - in modules

  • 파이썬에 이미 포함되어 있는 공식 라이브러리들

    <module 'sys' (built-in)>
    
    #sys 모듈은 이미 파이썬 설치시 포함되어 있는 모듈임

sys.path

  • 파이썬에서 마지막으로 확인하는 장소로, 리스트 내에 문자열 요소를 가지고 있음
    • 리스트 내 각 경로를 하나하나 확인하여 import 하고자 하는 패키지의 위치를 확인
   import sys
   print(sys.path)
   >>>
   ['/home/soohyung/PycharmProjects/untitled',
   '/home/soohyung/PycharmProjects/untitled',
   '/usr/lib/python38.zip', 
   '/usr/lib/python3.8', 
   '/usr/lib/python3.8/lib-dynload', 
   '/home/soohyung/PycharmProjects/untitled/venv/lib/python3.8/site-packages', 
   '/home/soohyung/PycharmProjects/untitled/venv/lib/python3.8/site-packages/setuptools-40.8.0-py3.8.egg', 
   '/home/soohyung/PycharmProjects/untitled/venv/lib/python3.8/site-packages/pip-19.0.3-py3.8.egg'
   ]
  • 3단계를 통해 모든 경로를 확인하고 결국 찾지 못하게 되면 ModuleNotFOundError를 리턴

절대 경로 & 상대 경로

절대 경로

  • 프로젝트의 최상단 디렉토리를 기준으로 경로를 지정하는 방식으로 import 하는 파일이나 경로에 상관 없이 항상 경로가 동일함

    • 위 그림에서 절대 경로를 통해 module5를 import하려면 아래의 경로로 가야함

      my_app / package2 / subpackage1 / module5.py

    • 파이썬에서는 slash 대신 dot을 통해 경로를 표현함

      my_app.package2.subpackage1.module5.py

    • my_app은 이미 프로젝트 안에 있어 생략하고 from import를 이용하면 아래와 같음

      from my_app.package2.subpackage1.module5 import function1

상대 경로

  • 상대 경로는 import하는 위치를 기준으로 경로를 정의하고 있으며 절대 경로의 사용 시 경로가 길어질 수 있는 단점을 보완하기 위해서 사용이 가능함

    • package2/module3에서 subpackage1의 module5를 import하려면,

      # package2/module3.py
      
      from .subpackage1.module5 import fuction2
      # subpackage 앞의 dot은 현재 위치를 의미함
    • subpackage1/module5에서 module4를 import하려면,

      #subpackage1/module5
      
      from ..module4 import class4
      # 상위 위치로 이동하기 위해서는 double dot(..)을 이용함
  • 그러나, 상대 경로를 사용하면 헷갈리기 쉬우며, 파일 위치의 변경 시 경로 위치도 변경되어야하는 단점이 있어 절대 경로의 사용이 권장

예제)

   # mod1.py
   def func1(a, b):
       return a * b
       
   # mod2.py
   def func2(a, b):
       return a + b
   
   # __init__.py
   from pkg.mod1 import func1		#== from .mod1 import func1(상대경로)
   from pkg.mod2 import func2		#== from .mod1 import func2(상대경로)
   
   # main.py
   from pkg import func1
   from pkg import func2
   
   a = func1(2, 3)
   b = func2(2, 3)
   
   print(f"""{a}, {b}, {a * b}""")
   >>> 6, 5, 30
profile
Slow and steady win the race

0개의 댓글