본문 바로가기

Python

220206 학습일기

1.

모듈은 당연히 클래스나 다른 변수도 포함할 수 있다.

 

mod1.py는 다음과 같다.

# mod1.py
def add(a,b):
    return a+b

def sub(a,b):
    return a-b

class Hi:
    def intro(self,name):
        print("Hi. This is {}".format(name))

if __name__ == "__main__":
    print(add(1,2))
    print(sub(1,2))

 

 

모듈 안에 잇는 클래스를 사용하려면 인스턴스를 정의할 때 클래스 이름 앞에 모듈 이름을 먼저 입력해야 한다.

인스턴스_이름 = 모듈이름.클래스_이름

 

 

2.

어떤 모듈 A가 있다.

다른 파이썬 파일 B에서 모듈 A를 불러오려면 A와 B가 동일한 디렉터리에 있어야한다.

 

 

3.

지금까지는 명령 프롬프트 창을 열고 모듈이 있는 디렉터리로 이동한 다음에 모듈을 사용할 수 있었다.
모듈을 저장한 디렉터리로 이동하지 않고 모듈을 불러와서 사용하는 방법을 알아보자.

 

먼저 mod1.py의 위치는 다음과 같다.

C:\tina

 

① sys.path.append(모듈을 저장한 directory) 사용하기

 

먼저 sys 모듈을 불러온다.

sys는 파이썬을 설치할 때 함께 설치되는 라이브러리 모듈이다.
sys 모듈을 사용하면 파이썬 라이브러리가 설치되어 있는 directory를 확인할 수 있다.

 

sys.path는 파이썬 library가 설치되어있는 directory를 보여준다.
만약 파이썬 모듈이 위 디렉터리에 들어 있다면 모듈이 저장된 디렉터리로 이동할 필요 없이 바로 불러서 사용할 수 있다. (우리가 C:\Python39\Lib 위치에 있는 random 모듈을 바로 import할 수 있는 것처럼)

 

그렇다면 sys.path에 C:/tina 디렉터리를 추가하면 아무 곳에서나 불러 사용할 수 있다.

# cmd
C:\Users\tina0>cd c:\tina

c:\tina>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', 'C:\\Python39\\python39.zip', 'C:\\Python39\\DLLs', 'C:\\Python39\\lib', 'C:\\Python39', 'C:\\Python39\\lib\\site-packages']
>>> sys.path.append("C:/tina")
>>> sys.path
['', 'C:\\Python39\\python39.zip', 'C:\\Python39\\DLLs', 'C:\\Python39\\lib', 'C:\\Python39', 'C:\\Python39\\lib\\site-packages', 'C:/tina']

명령 프롬프트에 sys.path를 입력하면 리스트가 출력되므로 append를 사용하여 sys.path에 C:/tina 디렉터리를 추가해줬다.

 

이제 mod1.py의 디렉토리인 C:/tina가 아닌 다른 디렉토리에서 mod1을 import해보자.

잘 된다.

 

 

그런데 여기서 주의해야할 점은 여기서 명령프롬프트를 끄면 sys.path에서 "C:/tina"는 지워진다.

즉, cmd를 실행할 때마다 sys.path는 초기화된다는 것이다.

 

 

②PYTHONPATH 환경변수 사용하기

 

set 명령어를 사용해 PYTHONPATH 환경 변수에 mod1.py 파일이 있는 C:/tina 디렉터리를 설정한다.
그러면 디렉터리를 이동이나 모듈 추가 작업 없이 mod1 모듈을 불러와서 사용할 수 있다.

 

이것도 ① 방법과 마찬가지로 cmd를 실행할 때마다 초기화된다.

 

cmd를 새로 실행했을 때의 모습이다.

# cmd
C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import mod1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'mod1'
>>> quit()

C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import mod1
>>> print(mod1.add(3,4))
7

 

 

4.

명령 프롬프트 창에 /든 \든 상관없지만, 소스 코드 안에서는 / 또는 \\를 사용해야 한다.

(\가 이스케이프 코드에 사용되어서 그런 것 같다.)

 


5.

패키지(Packages)는 도트(.)를 사용하여 파이썬 모듈을 계층적(directory 구조)으로 관리할 수 있게 해준다.
예를 들어 모듈 이름이 A.B 인 경우 A는 패키지 이름이 되고 B는 A 패키지의 B모듈이 된다.

 

파이썬 패키지는 directory와 파이썬 모듈로 이루어지며 구조는 아래와 같다.

game/
	__init__.py
	sound/
    		__init__.py
    		intro.py
        	ingame.py
        	ending.py
	graphic/
    		__init__.py
        	background.py
        	char1.py
        	char2.py
	play/
    		__init__.py
        	run.py
        	test.py

game 디렉터리가 이 package의 root 디렉터리이고 sound, graphic, play는 sub 디렉터리이다.

 

간단한 파이썬 프로그램이 아니라면 이렇게 패키지 구조로 파이썬 프로그램을 만드는 것이 공동 작업이나 유지 보수 등 여러 면에서 유리하다.
또한 패키지 구조로 모듈을 만들면 다른 모듈과 이름이 겹치더라도 더 안전하게 사용할 수 있다.

 

 

6.

C:/tina 위치에 있는 game 디렉토리의 구조는 다음과 같다.

 

intro.py는 다음과 같다.

# C:/tina/sound/intro.py
def intro_test():
    print("intro")

 

graphic.py는 다음과 같다.

# C:/tina/graphic/char1.py
def char1_test():
    print("char1")

 

이제 game 패키지를 참조할 수 있도록 명령 프롬프트 창에서 set 명령어로 PYTHONPATH 환경 변수에 C:/tina 디렉터리를 추가한다. 그리고 파이썬 인터프리터(interactive shell)를 실행한다.

 

 

위의 실습들과 아래의 실습들은 반드시 명령 프롬프트에서 파이썬 인터프리터를 실행하여 진행해야 한다.
IDLE 셸 또는 비주얼 스튜디오의 파이썬 셸에서 아래의 예제들을 실행하면 오류가 난다.

 

 

 

이제 패키지를 사용하여 intro.py 파일의 intro_test 함수를 실행해보자.
패키지 안의 함수를 실행하는 방법은 다음 3가지이다.

이때 주의해야 할 점은 한 가지 방법으로 수행하고 난 후 다른 방법으로 수행하고자 할 때는 반드시 인터프리터를 종료하고 다시 실행해야 한다.
인터프리터를 다시 시작하지 않을 경우 이전에 import한 것들이 메모리에 남아 있어 엉뚱한 결과가 나올 수 있다.

 

 

① intro 모듈을 import하여 실행하는 방법

C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import game.sound.intro
>>> game.sound.intro.intro_test()
intro

 

일반화하면 이렇다.

PYTHONPATH 환경변수에 설정된 디렉토리를 S라고 하고

S(디렉)/A(디렉)/B(디렉)/C(모듈) 인 A,B,C가 있고 모듈 C에 d라는 함수가 있다고 하자.

 

import A.B.C
A.B.C.d()

 

② intro 모듈이 있는 directory 까지를 from ... import하여 실행하는 방법

C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from game.sound import intro
>>> intro.intro_test()
intro

 

일반화하면 이렇다.

PYTHONPATH 환경변수에 설정된 디렉토리를 S라고 하고

S(디렉)/A(디렉)/B(디렉)/C(모듈) 인 A,B,C가 있고 모듈 C에 d라는 함수가 있다고 하자.

from A.B import C
C.d()

 

 

③ intro 모듈의 intro_test 함수를 직접 import하여 실행하는 방법

C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from game.sound.intro import intro_test
>>> intro_test()
intro

 

일반화하면 이렇다.

PYTHONPATH 환경변수에 설정된 디렉토리를 S라고 하고

S(디렉)/A(디렉)/B(디렉)/C(모듈) 인 A,B,C가 있고 모듈 C에 d라는 함수가 있다고 하자.

from A.B.C import d
d()

 

 

**하지만 여기서 주의할 점은

PYTHONPATH 환경변수에 설정된 디렉토리를 S라고 하고

S(디렉)/A(디렉)/B(디렉)/C(모듈) 인 A,B,C가 있고 모듈 C에 d라는 함수가 있다고 할 때,

import A.B.C.d
d()

이건 안된다.

 

도트 연산자(.)을 사용해서 import A.B.C처럼 import 할 때, 가장 마지막 항목인 C는 반드시 모듈 또는 패키지여야 한다.

 

C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import game.sound.intro.intro_test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'game.sound.intro.intro_test'; 'game.sound.intro' is not a package

 

 

7.

이렇게 명령프롬프트에서 python을 입력하는 것을 '파이썬 인터프리터를 실행한다'라고 한다.

 

 

8.__init__.py의 용도, __all__ 변수

 

__init__.py 파일은 해당 directory가 패키지의 일부임을 알려주는 역할을 한다.
만약 game,sound,graphic 등 패키지에 포함된 디렉터리에 __init__.py 파일이 없다면 패키지로 인식되지 않는다.

 

**python 3.3 버전부터는 __init__.py 파일이 없어도 패키지로 인식한다. 
하지만 하위 버전 호환을 위해 __init__.py 파일을 생성하는 것이 안전한 방법이다.

 

C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from game.sound import *
>>> intro.intro_test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'intro' is not defined

game.sound 패키지에서 모든 것(*)을 import하였으므로 intro 모듈을 사용할 수 있어야 할 것 같은데 intro라는 이름이 정의되지 않았다는 NameError이 발생했다.

 

 

이렇게 특정 directroy의 모듈을 *을 이용하여 import할 때에는 다음과 같이 해당 디렉터리의 __‌init__.py 파일에 __all__ 변수를 설정하고 import 할 수 있는 모듈을 정의해줘야 한다.

# C:\tina\game\sound\__init__.py
__all__ = ['intro']

여기서 __all__이 의미하는 것은 sound 디렉터리에서 * 기호를 사용해 import할 경우 이곳에 정의된 intro 모듈만 import된다는 의미이다.

 

C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from game.sound import *
>>> intro.intro_test()
intro

이제는 된다.

 

 

from game.sound.echo import * 은 __all__과 상관없이 무조건 import된다.


__all__과 상관없이 무조건 import되는 경우는 from a.b.c import *에서 from의 마지막 항목인 c가 모듈인 경우다.

 

 

9. 현재 directory, 부모 directory

 

모듈 C의 위치가 다음과 같다고 하자.

C:/A/B

 

C의 현재 디렉터리는 B이고

부모 디렉터리는 A이다.

 

 

<relative 접근자>

.. - 부모 디렉터리
. - 현재 디렉터리

 

 

10. relative 패키지

 

만약 C:\tina\game\graphic 위치의 char1.py에서 intro.py 모듈을 사용하고 싶다면 어떻게 해야할까?

 

먼저 char1.py를 고쳐주어야 한다.

정석은 아래와 같이 전체 경로를 사용하여 import하는 것이다.

# C:\tina\game\graphic\char1.py
def char1_test():
    print("char1")

from game.sound.intro import intro_test

def char1_change():
    print('char1_change')
    intro_test()

 

그런데 꼭 이렇게 해줄 필요 없이 relative하게 import도 가능하다.

# C:\tina\game\graphic\char1.py
def char1_test():
    print("char1")

from ..sound.intro import intro_test

def char1_change():
    print('char1_change')
    intro_test()

char1.py의 부모 디렉터리는 game이므로 sound앞에 ..을 해주면 된다.

 

#cmd
C:\Users\tina0>set PYTHONPATH=C:/tina

C:\Users\tina0>python
Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from game.graphic.char1 import char1_change
>>> char1_change()
char1_change
intro

명령 프롬프트에서는 ..이 안되는 것 같다.

 

 

[교재]

점프 투 파이썬

https://wikidocs.net/book/1

 

점프 투 파이썬

** 점프 투 파이썬 오프라인 책(개정판) 출간 !! (2019.06) ** * [책 구입 안내](https://wikidocs.net/4321) 이 책은 파이썬 ...

wikidocs.net

 

'Python' 카테고리의 다른 글

220209 학습일기  (0) 2022.02.10
220208 학습일기  (0) 2022.02.09
220203 학습일기  (0) 2022.02.06
220127 학습일기  (0) 2022.01.27
220123 학습일기  (0) 2022.01.23