1. Pacakge 구조

  • Packagemodule의 묶음을 의미하며, 폴더에 담아 관리한다.
  • pacakge를 불러와서 사용하기 위해서는 2가지 방법이 있다.
    • 첫 번째, 현재 경로를 기준으로 상대 경로 개념을 사용하여, module 경로를 직접 입력 하여 사용하는 방식
    • 두 번째 방법: importfrom을 사용하는 방식
  • 경로 이동: cd .. 을 하면 ‘상위 directory’로 이동
  • 여러 명과 project를 진행한다면 위 방법 2가지 보다는 컴퓨터 공용 위치에 package 파일들을 두고, sys.path 또는 환경설정에서 경로를 설정하는 방법을 사용하자.

 

2. 패키지 경로 및 패키지 함수 실행

2.1 패키지 경로 와 inspect.getfile 함수

  • 예제를 설명하기에 앞서 module로 사용할 package인 module1.pymodule2.py의 위치는 다음과 같다.
  • __init__.py 파일도 기억해놓자.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
sub
├─sub1
│  │─ module1.py
│  │─ __init__.py
│  └─ __pycache__
├─sub2
│  │─ module2.py
│  │─ __init__.py
│  └─__pycache__
└─__pycache__
  • 그리고 module 파일인 module1.pymodule2.py의 내부 코드는 다음과 같다.
  • inspect 함수는 파이썬의 객체들로부터 유용한 정보를 얻고자 할 때 사용하는 함수다.
  • inspect 에 의해 제공되는 함수가 .getfile 이다.
    • .getfileobject가 어느 위치에 있는지 알고자 할 때 사용한다.
  • .currentframe실행 중인 파일의 이름과 경로를 보여준다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## module1.py
> import sys
> import inspect
# from ..sub2 import module2


> def mod1_test1():
> 	print ("Module1 -> Test1")
> 	print("Path : ", inspect.getfile(inspect.currentframe()))


> def mod1_test2():
> 	print ("Module1 -> Test2")
> 	print("Path : ", inspect.getfile(inspect.currentframe()))

# 만약 inspect.currentframe()만 입력하면 다음과 같이 뜬다.
#  <frame at 0x00000296CE1BB7C0, file c:\\Users ~~ \module1.py, line 9, code mod1_test1>
# 파일 경로와, 파일 내의 몇 번째 줄인지까지 확인할 수 있다.

# 하지만, insepct.getfile(inspect.currentframe())) 을 입력하면 다음과 같이 뜬다.
#  c:\Users\ ~ sub\sub1\module1.py
# 경로만 출력된다.

# 코드 경로를 넘어서 더 상세한 위치를 알고 싶다면 `inspect.currentframe()`을 사용해야겠다.


## module2.py
> import sys
> import inspect

> def mod2_test1():
> 	print ("Module2 -> Test1")
> 	print("Path : ", inspect.getfile(inspect.currentframe()))


> def mod2_test2():
> 	print ("Module2 -> Test2")
> 	print("Path : ", inspect.getfile(inspect.currentframe()))

 

2.2 패키지 함수 실행하기: 2가지 방법

  • 첫 번째, 경로를 하나 하나 입력하는 것
  • 두 번째, from ~ import ~ as 사용하기
  • 그러면 패키지를 불러오는 방법 2가지에 대해 알아보자.

  • 폴더명을 입력하고 점.을 입력하면 입력했던 폴더명의 하위 object가 뜬다.

    • 폴더, 파일, method 등등이 뜬다.

 

  • 첫 번째 방법
    • 단점:
      • 경로가 너무 다르면 입력해야할 경로가 너무 길어진다.
      • 그래서 현재 경로와 같을 경우에 사용한다.
      • 경로가 길어질 경우를 대비해서 from을 사용한다. (두 번째 방법)
    • 장점:
      • sys.path.append() 함수로 경로를 추가하지 않아도 불러올 수 있다.
1
2
3
4
5
6
7
8
9
## 첫 번째 방법

> sub.sub1.module1.mod1_test1()
> sub.sub2.module2.mod2_test1()

# 또는

> import sub.sub1.module1
> import sub.sub2.module2

 

  • 두 번째 방법
    • 첫 번째보다 경로를 짧게 입력할 수 있기 때문에, 깔끔하고 가독성이 좋다.
    • from을 통해 사용하고 싶은 모듈만 import 하여 사용한다.
    • asalias로 별명, 별칭이다.
    • as를 설정하면 모듈 이름을 다 입력할 필요 없이, as만 입력하면 된다.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
## 두 번째 방법
> from sub.sub1 import module1
> from sub.sub2 import module2 as m2

# 호출하기
> module1.mod1_test1()
Module1 -> Test1
Path :  c:\Users\ ~ \sub\sub1\module1.py
> module1.mod1_test2()
Module1 -> Test2
Path :  c:\Users\ ~ \sub\sub1\module1.py

# 아래 2가지는 서로 같다.
> module2.mod2_test1()
> m2.mod2_test1()
Module2 -> Test1
Path :  c:\Users\ ~ \sub\sub2\module2.py

 

  • from ~ import * 로 모든 module 파일을 가져올 수도 있다.
    • * 이 모든 파일을 의미한다.
  • 하지만 이런 경우 안쓰는 파일을 가져오는데, 현재 HW의 발달로 눈에 띄는 성능 저하는 드러나지 않지만, 이런 것들이 쌓이면 run time에서 메모리를 잡아먹는다.
  • 항상 메모리 를 신경쓰는 습관을 가지자.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
> from sub.sub1 import *
> from sub.sub2 import *

> module1.mod1_test1()
Module1 -> Test1
Path :  c:\Users\ ~ \sub\sub1\module1.py
> module1.mod1_test2()
Module1 -> Test2
Path :  c:\Users\ ~ \sub\sub1\module1.py


> module2.mod2_test1()
Module2 -> Test1
Path :  c:\Users\ ~ \sub\sub2\module2.py
> module2.mod2_test2()
Module2 -> Test2
Path :  c:\Users\ ~ \sub\sub2\module2.py

3. __init__.py 가 존재하는 이유

파이썬에게 해당 폴더가 패키지임을 알려준다. 이 파일이 없으면 패키지로 인식하지 않는다. Python 3.3부터는 __init__.py 파일이 없어도 패키지로 인식한다.

  • 그러면 __init__.py 을 작성할 필요가 없을까?? 아니다.
    • Python 3.3 이전 버전으로 의뢰가 들어올 경우가 있기 때문에, 그리고 하위 호환을 위해 작성한다.
    • Python 3.3 이전 버전으로 작성하다가 새롭게 업데이트를 하면 거의 작동되겠지만, 예상치 못한 side effect가 있을 수 있기 때문에 작성한다.
  • package 폴더에 있는 pyecache 파일은 빠른 실행을 위해 파이썬 엔진이 만드는 것이기 때문에, 지워도 실행하면 다시 생긴다.

 

  • 그러면 __init__.py 파일 내부를 살펴보자.
1
2
3
4
5
6
7
# sub1 폴더에는 module1.py 이 있다.
# sub1 의 __init__.py 작성 명령어는 다음과 같다.
> __all__ = ['module1']

# sub2 폴더에는 module2.py 이 있다.
# sub2 의 __init__.py 작성 명령어는 다음과 같다.
> __all__ = ['module2']
  • 아래 내용은 Python 3.3 이전 버전에 관한 내용이다. 이후부터는 필수가 아니다.
    • __all__ = [ ] 에서 대괄호에 module 파일명이 적혀 있어야, 외부에서 import 할 때 해당 module 파일을 허가해준다.
    • 이 list에 파일명이 다르면 작동할 수 없다.
    • 파이썬이 import할 때, __init__을 먼저 검사하기 때문에, all에 없으면 error가 발생된다.
  • Python 3.3부터는 __init__.py 가 필수가 아니어도, 아직 많은 오픈 소스에는 존재한다.

 


Reference