[불사조] Python study (3)
팀원 : 김승혁 류건희 박지현 이예주 임은진 조준혁
3주차 내용은 이전글에 이어서 작성했습니다(링크참고)
https://khu-code.tistory.com/116
클래스의 상속
- 클래스의 상속이란? > 어떠한 클래스를 만들 때 다른 클래스의 기능을 물려받을 수 있게 만듦!
고로 예를 들어 위의 Fourcal 클래스를 상속하는 MoreFourcal 클래스(a의 b제곱을 계산하게끔)를 만들어보자면
이때, MoreFourcal 클래스는 기존 클래스의 기능을 모두 사용 가능
MoreFourcal 클래스에 Pow 메서드를 추가해서 호출하면 리턴값이 나오게끔 구성
즉, 상속은 기존 클래스는 그대로 놔둔채 클래스의 기능을 확장할 때 주로 사용
메서드 오버라이딩
- 부모 클래스에 있는 메서드를 동일한 이름으로 다시 만드는 것
이때, SafeFourcal 클래스를 만들어서 0을 리턴하도록 해보자면
클래스 변수
객체변수 VS 클래스 변수
객체변수 : 다른 객체들의 영향을 받지 않고 독립적으로 그 값을 유지함
클래스 변수 : 클래스로 만든 모든 객체에 공유됨
예를 들어)
+ 클래스변수와 동일한 이름의 객체변수를 생성하더라도 서로 영향을 받지 않음
05 -2 모듈
- 모듈이란? > 함수나 변수 또는 클래스를 모아 놓은 파이썬 파일
이렇게 설정해둔 모듈을 C :/doit 디렉터리로 옮긴 후 import mod1을 통해 모듈을 불러오기
** 이때, import 는 이미 만들어 놓은 파이썬 모듈을 사용할 수 있게 하는 명령어
그치만 불러온 모듈에 이름을 붙이지 않고 함수 이름만 쓰고 싶은 경우에는 아래 두가지 경우 사용
만약에 mod1에 있는 add, sub 함수만 불러오고 싶은데 결괏값이 출력될 때에는 어떻게 해야할까?
직접 파일을 실행하지 않고 다른 파일에서 모듈을 불러올 때 사용할 때에 저 if문은 거짓이 되어 수행 X
=> 원하는 함수만 불러오기 가능!
클래스나 변수 등을 포함한 모듈
-클래스, 변수, 함수 모두 모듈에 포함 가능
그러므로 import mod2 >>> print(mod2.PI)하면 원주율의 값인 3.141592 가 나타남
a = mod2.Math() >>> print(a.solv(2))하면 원주율의 값 ** 2의 2 제곱한 12.566368 이 나타남
print(mod2.add(mod2.PI, 4.4))하면 원주율의 값에 4.4를 더한 7.541592가 나타남
05-3 패키지
- 패키지란? > 관련 있는 모듈의 집합을 말함
전체 C :/doit 디렉터리 밑에 game 디렉터리 안에 sound, graphic, play 서브 디렉터리 생성
패키지 안의 함수 실행하기
패키지 안의 함수를 실행하는 방법에는 3 가지가 있다. 다음은 import 예제이므로 하나의 예제를 실행하고 나서 다음 예제를 실행할 때는 반드시 인터프리터를 종료하고 다시 실행해야 한다.
첫 번째는 echo 모듈을 import 하여 실행하는 방법으로, 다음과 같이 실행한다.
>>> import game.sound.echo
>>> game.sound.echo.echo_test()
echo
두 번째는 echo 모듈이 있는 디렉터리까지를 from ... import하여 실행하는 방법이다.
>>> exit()
C:\> python
>>> from game.sound import echo
>>> echo.echo_test()
echo
세 번째는 echo 모듈의 echo_test 함수를 직접 import 하여 실행하는 방법이다.
>>> from game.sound.echo import echo_test
>>> echo_test()
echo
__init__.py 의 용도
__init__.py 파일은 해당 디렉터리가 패키지의 일부임을 알려 주는 역할을 한다. 만약 game, sound, graphic 등 패키지에 포함된 디렉터리에 __init__.py 파일이 없다면 패키지로 인식되지 않는다.
패키지 변수 및 함수 정의
패키지 수준에서 변수와 함수를 정의할 수 있다. 예를 들어, game 패키지의 __init__.py 파일에 공통변수나 함수를 정의할 수 있다.
VERSION = 3.5
def print_version_info():
print(f"The version of this game is {VERSION}.")
__init__.py 파일에 정의된 변수와 함수는 다음과 같이 사용할 수 있다.
>>> import game
>>> print(game.VERSION)
3.5
>>> game.print_version_info()
The version of this game is 3.5.
패키지 내 모듈을 미리 import
__init__.py 파일에 패키지 내의 다른 모듈을 미리 import 하여 패키지를 사용하는 코드에서 간편하게 접근할 수 있게 한다.
패키지 초기화
__ini__.py 파일에 패키지를 처음 불러올 때 실행되어야 하는 코드를 작성할 수 있다
이렇게 하면 패키지를 처음 import 할 때 초기화 코드가 실행된다.
>>> import game
Initializing game ...
>>>
game 패키지의 초기화 코드는 game 패키지의 하위 모듈의 함수를 import 할 경우에도 실행된다. 단, 초기화 코드는 한 번 실행된 후에는 다시 import 를 수행하더라도 실행되지 않는다.
__all__
다음을 따라하면 echo 라는 이름이 정의되지 않았다는 오류가 발생했다.
이렇게 특정 디렉터리의 모듈을 *를 사용하여 import 할 때는 다음과 같이 해당 디렉터리의 __init__.py 파일에 __all__ 변수를 설정하고 import 할 수 있는 모듈을 정의해 주어야 한다.
# C:/doit/game/sound/__init__.py
__all__ = ['echo'] 은 sound 디렉터리에서 *를 사용하여 import 할 경우, 이곳에 정의된echo 모듈만 import 된다는 의미이다.
__init__.py 파일을 변경한 후 예제를 수행하면 원하는 결과가 출력된다.
relative 패키지
만약 graphic 디렉터리의 render.py 모듈에서 sound 디렉터리의 echo.py 모듈을 사용하고 싶다면 render.py 를 수정하면 가능하다
echo_test 함수를 사용할 수 있도록 수정했다. 이렇게 수정한 후 다음과 같이 실행해 보자.
>>> from game.graphic.render import render_test
Initializing game ...
>>> render_test()
render
echo
위처럼 import 할 수도 있지만, 다음과 같이 relative 하게 import 하는 것도 가능하다.
..은 render.py 파일의 부모 디렉터리를 의미한다. 따라서render.py 파일의 부모 디렉터리는 game 이므로 위와 같은 import 가 가능한 것이다.
relative 한 접근자에는 다음과 같은 것이 있다.
relative 한 접근자에는 다음과 같은 것이 있다
05‑4 예외 처리
오류는 언제 발생하는가?
구문 오류 같은 것이 아닌 실제 프로그램에서 자주 발생하는 오류를 중심으로 살펴보자.
먼저 존재하지 않는 파일을 사용하려고 시도했을 때 발생하는 오류이다.
FileNotFoundError 오류가 발생한다.
4 를 0 으로 나누려고 하니 ZeroDivisionError 오류가 발생한다.
a[3] 은 a 의 네 번째 요솟값을 가리키는데, a 리스트에는 값이 3 개밖에 없으므로
([1, 2, 3]) 값을 얻을 수 없다. 따라서 IndexError 오류가 발생한다.
오류 예외 처리 기법
try except 문
오류를 처리하기 위한 try except 문의 기본 구조이다.
try 블록 수행 중 오류가 발생하면 except 블록이 수행된다.
하지만 try 블록에서 오류가 발생하지 않는다면 except 블록은 수행되지 않는다.
위 구문을 보면 [] 를 사용하는데, 이 기호는 괄호 안의 내용을 생략할 수 있다는 관례적인 표기법이다. except 구문은 다음 3 가지 방법으로 사용할 수 있다.
1. try‑except 만 쓰는 방법
오류의 종류에 상관없이 오류가 발생하면 except 블록을 수행한다.
2. 발생 오류만 포함한 except 문
오류가 발생했을 때 except 문에 미리 정해 놓은 오류와 동일한 오류일 경우에만 except 블록을수행한다는 뜻이다.
3. 발생 오류와 오류 변수까지 포함한 except 문
두 번째 경우에서 오류의 내용까지 알고 싶을 때 사용하는 방법이다.
try‑finally 문
finally 절은 try 문 수행 도중 예외 발생 여부에 상관없이 항상 수행
된다. 보통 finally 절은 사용한 리소스를 close 해야 할 때 많이 사용한다.
여러 개의 오류 처리하기
try 문 안에서 여러 개의 오류를 처리하기 위한 구조는 다음과 같다.
a 는 2 개의 요솟값을 가지고 있으므로 a[3] 이 IndexError 를 발생시켜 “인덱싱할 수 없습니다.” 라는 문자열을 출력할 것이다. 인덱싱 오류가 먼저 발생했으므로 4/0에 따른 ZeroDivisionError 오류는 발생하지 않는다.
‘list index out of range’ 라는 오류 메시지가 출력될 것이다.
2 개 이상의 오류를 동일하게 처리하기 위해서는 위와 같이 괄호를 사용하여 함께 묶어 처리하면 된다.
try‑else 문
try 문에는 다음처럼 else 절을 사용할 수도 있다.
try 문 수행 중 오류가 발생하면 except 절, 오류가 발생하지 않으면 else 절이 수행된다.
오류 회피하기
코드를 작성하다 보면 특정 오류가 발생할 경우 그냥 통과시켜야 할 때가 있다.
pass 를 사용하여 오류를 그냥 회피하도록 작성한 예제이다.
오류 일부러 발생시키기
프로그래밍을 하다 보면 종종 오류를 일부러 발생시켜야 할 경우도 생긴다. 파이썬은 raise 명령어를 사용해 오류를 강제로 발생시킬 수 있다. 다음 예를 보자
Bird 클래스를 상속받는 자식 클래스는 반드시 fly 함수를 구현해야 한다는 의지를 보여 준다. 만약 자식클래스가 fly 함수를 구현하지 않은 상태로 fly 함수를 호출한다면 어떻게 될까?
eagle 객체의 fly 메서드를 수행하는 순간 Bird 클래스의 fly 메서드가 수행되어
NotImplementedError 가 발생한다.
NotImplementedError 가 발생하지 않게 하려면 다음과 같이 Eagle 클래스에 fly 함수를 구현해야 한다.
예외 만들기
프로그램을 수행하다가 특수한 경우에만 예외 처리를 하려고 종종 예외를 만들어서 사용한다
별명을 출력하는 함수
그리고 천사, 바보로 say_nick 함수를 호출해 보자.
프로그램을 실행해 보면 다음과 같이 “천사” 가 한 번 출력된 후 MyError 가 발생한다.
이번에는 예외 처리 기법을 사용하여 MyError 발생을 예외 처리해 보자.
만약 오류 메시지를 사용하고 싶다면 다음처럼 예외 처리를 하면 된다.
05‑5 내장 함수
우리는 이미 몇 가지 내장 함수를 배웠다. print, del, type 등이 바로 그것이다. 이러한 파이썬 내장 함수는 파이썬 모듈과 달리 import가 필요하지 않기 때문에 아무런 설정 없이 바로 사용할 수 있다. 그렇기에 새로운 프로그램을 만들기 전에 이미 만들어진 함수를 살펴보자
p. 242
- abs 함수 => 절댓값
- all 함수 => 반복가능한 데이터(리스트,튜플,문자열,딕셔너리,집합)의 요소가 모두 참이면 True, 하나라도 거짓이면 False
- any 함수 => all함수의 반대/ 요소가 하나라도 참-> True, 모든 요소가 거짓-> False
- chr 함수 => 유니코드 입력하면 해당 문자 리턴함
- dir 함수 => 객체의 변수와 함수 리턴함
- divmod 함수 => 앞/뒤의 몫, 나머지를 튜플로 출력함
- enumerate 함수 => for문과 함께 사용/ 리스트,튜플,문자열의 인덱스값과 요소 함께 출력
- eval 함수 => 문자열로 함수,
연산 등을 입력하면 실행해서 리턴함
- filter 함수 -> 걸러내어서 리턴하는 함수
- hex 함수 -> 16진수 문자열로 변환
- id 함수 -> 객체의 고유 주소값을 리턴
- input 함수 -> 사용자 입력을 받는 함수
- int 함수 -> 정수로 변환함
- isinstance 함수 -> isinstance(object, class) 객체가 참이면True, 거짓이면False
- len 함수 -> 입력값의 길이 구하는 함수
- list 함수 -> 리스트로 변환하는 함수
- map 함수 -> map(f,iterable) 함수와 반복가능한 데이터를 입력받고 각 literable데이터의 함수를 적용한 결과 리턴
- max 함수 -> max(iterable) 반복가능한 데이터 중 최댓값 리턴
- min 함수 -> min(literable) 최솟값 리턴
- oct 함수 -> oct(x)/ 8진수 문자열로 변환하여 출력
- open 함수 -> open(filename, [model])
b는 r,w,a와 함께 사용함.
mode | 설명 |
w | 쓰기 모드로 파일 열기 |
r | 읽기 모드로 파일 열기 |
a | 추가 모드로 파일 열기 |
b | 바이너리 모드로 파일 열기 |
- ord 함수 -> ord('문자열') 문자의 유니코드 숫자값 리턴
- pow 함수 -> pow(x,y) x를 y제곱한 결과값 출력
- range 함수
- round 함수 -> 반올림해서 리턴
- sorted 함수 -> 오름차순, 알파벳순으로 정렬 후 리스트로 리턴
- str 함수 -> 문자열 형태로 변환
- sum 함수 -> sum(iterable) 입력 데이터의 합을 리턴
- tuple 함수 -> 튜플로 변환
- type 함수 -> 입력값의 자료형 알려주는 함수
- zip 함수 -> zip(iterable)/ 같은 순서의 요소끼리 묶어서 출력
05-6 표준 라이브러리
파이썬 표준 라이브러리-> 유용한 프로그램 모아놓은 곳, 파이썬 설치 중 자동으로 설치됨,
상황에 맞는 라이브러리 어떻게 사용하는지만 알면 됨-> 다 알 필요는 없음
import (모듈명)을 통해 임포트한후, 내장함수들을 사용할 수 있음
대표적인 표준 라이브러리
1)datetime모듈
datetime.date: 연,월,일로 날짜를 표현할 때 사용하는 함수
(객체).weekday(): 요일을 숫자로 출력하는 함수 (0=월요일)
(객체).isoweekday():요일을 숫자로 출력하는 함수 (1=월요일)
import datetime
day1 = datetime.date(2024, 4, 1) #월요일
day2 = datetime.date(2024, 4, 30)
print(day2 - day1)
print(day1.weekday()) #월요일=0
print(day1.isoweekday()) #월요일=1
#출력
29 days, 0:00:00
0
1
2)time모듈
time.time(): 현재시간을 실수 형태로 리턴하는 함수
time.localtime(): time.time함수를 이용해서 리턴된 실수값을 사용해서 연,월,일,시,분,초의 (튜플)형태로 바꾸어주는 함수
time.asctime(): time.localtime가 리턴된 튜플형태의 값을 인수로 받아서 날짜와 시간을
알아보기 쉬운 형태로 리턴하는 함수
time.ctime = time.asctime(time.localtime(time.time()))이나, time.ctime은 현재시간만을 리턴한다는 점에서 차이가 있다.
time.strftime: 시간에 관련된 것을 세밀하게 표현하는 여러가지 포맷코드 제공
>>> time.strftime('출력할형식포맷코드', time.localtime(time.time()))의 형태로 작성함
import time
print(time.time())
print(time.localtime(time.time()))
print(time.asctime(time.localtime(time.time())))
print(time.ctime())
#출력
1711980085.7091227
time.struct_time(tm_year=2024, tm_mon=4, tm_mday=1, tm_hour=14, tm_min=1, tm_sec=25, tm_wday=0, tm_yday=92, tm_isdst=0)
Mon Apr 1 14:01:25 2024
Mon Apr 1 14:01:25 2024
time.sleep(시간간격): 루프를 실행할 때 주로 이용되는 함수로, 인수가 되는 시간간격은
실수형태(소수형태)도 사용이 가능하다
#time.sleep예시
#2초 간격으로 0부터 20까지를 출력하는 프로그램
import time
for i in range(20):
print(i)
time.sleep(2) #2초의 텀을 두고 반복문을 수행한다.
**time.localtime, time.asctime, time.strftime 함수는 입력 인수없이 사용할 수 있다.
(만약,입력 인수 없이 사용할 경우 현재 시각을 기준으로 함수가 수행된다.)
3)math모듈
math.gcd(숫자1,숫자2, ... ): 입력된 인수들의 최대공약수를 구하는 함수
math.lcm(숫자1,숫자2, ... ): 입력된 인수들의 최소 공배수를 구하는 함수
**파이썬3.9버전 부터는 math.gcd에 여러개의 인수를 입력할 수 있지만, 3.9미만 버전에서는 2개까지만 허용된다.
**math.lcm() 함수는파이썬3.9버전부터사용할수있다.
4)random 모듈 : 난수(규칙이 없는 임의의 수)를 발생시키는 모듈
random.random() : 0.0 ~1.0 의 실수 중 난수 값을 리턴하는 함수
random.randint(시작값, 끝값): 시작값~끝값까지의 정수중에서 난수값을 리턴
(range 와 달리 끝값도 난수범위에 포함시켜준다.)
random.choice(): 입력으로 받은 리스트 등의 인수에서 무작위로 하나를 선택하여 리턴하는 함수
random.sample(인수, 추출할 원소개수): 입력한 개수의 원소를 무작위로 추출하는 함수
(개수를 안쓰면 순서를 랜덤하게 바꿔주는 용도로도 쓰일 수 있다.)
5)itertools모듈
itertools .zip_longest(*iterables, fillvalue=None)함수
: zip()과 같은 동작을 하는 함수
:같은 개수의 자료형을 묶는 함수
묶으려는 자료형의 원소개수가 다른 경우 부족한 항목은 None으로 채우는데,
요소 개수가 많은것을 기준으로 자료형을 묶는 itertools.zip_longest()를사용하면
fillvalue로 부족한 값을 채울 값을 지정하면 None대신 다른값으로 채울 수도 있다.
itertools.permutations(iterable, r): 반복 가능한 객체중에서 r개를 선택한 순열을 이터레이터
(반복 가능한 개체)로 리턴하는 함수
itertools.combinations(iterable, r): 반복 가능한 객체중에서 r개를 선택한 조합을 리턴하는 함수
*iterable자리에 range()를 이용해 범위를 넣을 수도 있다.
#입력: 1~20중 숫자 6개를 뽑는 경우의 수를 세는 프로그램
import itertools
len(list(itertools.combinations(range(1, 20), 6)))
#출력
27132
itertools.combinations_with_replacement(): 중복조합(같은 숫자의 반복을 허용하는 조합)을 리턴하는 함수
functools.reduce(function, iterable): 함수(function) 를 반복가능한 객체(iterable)
의 요소에 차례대로 (왼쪽에서 오른쪽으로) 누적 적용하여 이객체를 하나의 값으로 줄이는 함수
+) functools.reduce(function, iterable): 함수(function) 를 반복가능한 객체(iterable)
의 요소에 차례대로 (왼쪽에서 오른쪽으로) 누적 적용하여 이객체를 하나의 값으로 줄이는 함수
6)operator.itemgetter모듈 ( from operator import itemgetter로 임포트해준다.)
sorted(분류할 대상, k매개변수=itemgetter(n)): n+1번째요소를 기준으로 대상을 정렬하는 함수
+)만약 분류할 대상이 클래스의 객체라면 다음처럼 attrgetter()를 적용하여 정렬해야 한다.
#입력
from operator import itemgetter
students = [
("a", 22, 'A'),
("b", 32, 'B'),
("c", 19, 'B'),
("d", 75, 'B'),
("e", 17, 'B'),
]
result = sorted(students, key=itemgetter(1)) #튜플의 두번째 요소(나이)를 기준으로 정렬하도록 한 명령어
print(result)
#출력
[('e', 17, 'B'), ('c', 19, 'B'), ('a', 22, 'A'), ('b', 32, 'B'), ('d', 75, 'B')]
shutil
shutil은 파일을 복사하거나 이동할 때 사용하는 모듈이다.
shutil을 사용한 방법이다.
glob
파일을 읽고 쓰는 기능이 있는 프로그램을 만들다 보면 특정 디렉터리에 있는 파일 이름 모두를 알아야 할 때가 있다.
이럴 때 사용하는 모듈이 바로 glob이다.
디렉터리에 있는 파일들을 리스트로 만들기 - glob(pathname)
glob 모듈은 디렉터리 안의 파일들을 읽어서 리턴한다. *,? 등 메타 문자를 써서 원하는 파일만 읽어 들일 수도 있다.
(?는 1자리 문자열, *은 임의의 길이의 문자열을 의미한다.)
다음은 C:doit 디렉터리에 있는 파일 중 이름이 mark로 시작하는 파일을 모두 찾아서 읽어드리는 예이다.
pickle
pickle은 객체의 형태를 그대로 유지하면서 파일에 저장하고 불러올 수 있게 하는 모듈이다.
pickle 모듈의 dump 힘수를 시용하여 딕셔너리 객체인 data를 그대로 파일에 저장하는 방법이다. 다음은 pickle.dump로 저장한 파일을 pickle.load를 사용해서 원래 있던 딕셔너리 객체 상태 그대로 불러오는 예이다.
OS
os 모듈은 환경 변수나 디렉터리, 파일 등의 OS 자원을 제어할 수 있게 해 주는 모듈이다.
내 시스템의 환경 변숫값을 알고 싶을 때 - os.environ
시스템은 제각기 다른 환경 변숫값을 가지고 있는데, os.environ은 현재 시스템은 환경 변숫값을 리턴한다.
os.environ은 환경 변수에 대한 정보를 딕셔너리 형태로 구성된 environ 객체로 리턴한다.리턴받은 객체는 다음과 같이 호출하여 사용할 수 있다.
디렉터리 위치 변경하기 - os.chdir
os.chdir를 사용하면 다음과 같이 현재 디렉터리의 위치를 변경할 수 있다.
디렉터리 위치 돌려받기 - os.getcwd
os.getcwd는 현재 자신의 디렉터리 위치를 리턴한다.
시스템 명령어 호출하기 - os.system
시스템 자체의 프로그램이나 기타 명령어를 파이썬에서 호출할 수도 있다.
현재 디렉터리에서 시스템 명령어 dir을 실행하는 예이다.
실행한 시스템 명령어의 결괏값 돌려받기 - os.popen
os.popen은 시스템 명령어를 실행한 결괏값을 읽기 모드 형태의 파일 객체로 리턴한다.
이 밖에 유용한 os 관련 함수는 다음과 같다.
zipfile
zipfile은 여러개의 파일을 zip 형식으로 합치거나 이를 해제할 때 사용하는 모듈이다.
다음과 같이 3개의 텍스트 파일이 있다고 가정하자.
이 3개의 텍스트 파일을 하나로 합쳐 'mytext.zip'이라는 파일을 만들고 이 파일을 원래의 텍스트 파일 3개로 해제하는
프로그램을 만들려면 zipfile.ZipFile()을 사용하여 해결하면 된다.
ZipFile 객체의 write()함수로 개별 파일을 추가할 수 있고 extreactall() 함수를 사용하면 모든 파일을 해제 할 수 있다.합친 파일에서 특정 파일만 해제하고 싶다면 extract()함수를 사용하면 된다.
만약 파일을 압축하여 묶고 깊은 경우에는 compression, compresslevel 옵션을 사용할 수 있다.
compression에는 4가지 종류가 있다.
- ZIP_STORED: 압축하지 않고 파일을 zip으로만 묶는다. 속도가 빠름.
- ZIP_DEFLATED: 일반적인 zip 압축으로 속도가 빠르고 압축률은 낮다. 호환성이 좋음.
- ZIP_BZIP2: bzip2 압축으로 압축률이 높고 속도가 느리다.
- ZIP_LZMA: lzma 압축으로 압축률이 높고 속도가 느리다.
threading
컴퓨터에서 동작하고 있는 프로그램을 프로세스(process)라고 한다. 보통 1개의 프로세스는 1가지 일만 하지만, 스레드(thread)를 사용하면 한 프로세스 안에서 2가지 또는 그 이상의 일을 동시에 수행할 수 있다.
long_task는 수행하는 데 5초의 시간이 걸리는 함수이다. 위 프로그램은 이 함수를 총 5번 반복해서 수행하는 프로그램이다. 이 프로그램은 5초가 총 5번 반복되므로 총 25초의 시간이 걸린다.스레드를 사용하면 5초의 시간이 걸리는 long_task함수를 동시에 실행할 수 있으므로 시간을 줄일 수 있다.
위와 같이 프로그램을 수정하고 실행해 보면 25초 걸리던 작업이 5초 정도에 수행되는 것을 확인할 수 있다.
threading.Thread를 사용하여 만든 스레드 객체가 동시 작업을 가능하게 해 주기 때문이다.
그러나 프로그램을 실행해 보면 "Start" 와 "End" 가 먼저 출력되고 그 이후에 스레드의 결과가 출력되는 것을
확인할 수 있다. 그리고 프로그램이 정상 종료되지 않는다.
"Start"가 출력되고 그 다음 스레드의 결과가 출력된 후 마지막으로 "End"가 출력될거라 기대한 것과는 다르다.
이 문제를 해결하기 위해선 다음과 같이 수정해야 한다.
스레드의 join함수는 해당 스레드가 종료될 때까지 기다리게 한다. 따라서 위와 같이 수정하면 우리가 원하던 출력을 보게 된다.tempfile
파일을 임시로 만들어서 사용할 때 유용한 모듈이다.
tempfile.mkstemp()는 중복되지 않는 임시 파일의 이름을 무작위로 만들어서 리턴한다.
tempfile.TemporaryFile() 은 임시 저장 공간으로 사용할 파일 객체를 리턴한다.
이 파일은 기본적으로 바이너리 쓰기 모드(wb)를 갖는다. f.close()가 호출되면 이 파일은 자동으로 삭제된다.
traceback
taceback은 프로그램 실행 중 발생한 오류를 추적하고자 할 때 사용하는 모듈이다.
위 프로그램을 실행하면 "오류가 발생했습니다."라는 결과가 나온다.
main()함수가 시작되면 b() 함수를 호출하고 b()함수에서 다시 a()함수를 호출하여 1을 0으로 나누므로 오류가 발생하여
"오류가 발생했습니다."라는 메세지를 출력했다.
이 코드에서 오류가 발생한 위치와 원인을 정확하게 판단할 수 있도록 코드를 업그레이드 하려면 다음과 같이 하면된다.
오류가 발생한 위치해 print(traceback.format_exc()) 문장을 추가했다.
traceback 모듈의 format_exc()는 오류 추적 결과를 문자열로 리턴하는 함수이다.
코드를 이렇게 수정하고 다시 프로그램을 실행하면 다음과 같이 출력된다.
ZeroDivisionError 가 발생했다는 것을 로그를 통해 정확하게 확인할 수 있다.
json
이것은 JSON 데이터를 쉽게 처리하고자 사용하는 모듈이다.
개인정보를 JSON 형태의 데이터로 만든 myinfo.json 파일이다.
인터넷으로 얻은 이 파일을 읽어 파이썬에서 처리할 수 있도록 딕셔너리 자료형으로 만들려면 아래처럼 json 모듈을 사용하면 된다.
JSON 파일을 읽을 때는 이 예시처럼 json.load(파일_객체)를 사용한다.
이렇게 load()함수를 읽은 데이터를 딕셔너리 자료형으로 리턴한다.
이와 반대로 딕셔너리 자료형을 JSON 파일로 생성할 때는 다음처럼 json.dump(딕셔너리, 파일_객체)를 사용한다.
파이썬 자료형을 JSON 문자열로 만드는 방법은 다음과 같다.
딕셔너리 자료형을 JSON 문자열로 만들려면 json.dumps()함수를 사용하면 된다.
그런데 딕셔너리를 JSON 데이터로 변경하면 '홍길동'과 같은 한글 문자열이 코드 형태로 표시된다.
dump(), dumps() 함수는 기본적으로 데이터를 아스키 형태로 저장하기 때문이다.
유니코드 문자열을 아스키 형태로 저장하다 보니 한글 문자열이 깨진 것 처럼 보인다.
하지만 JSON 문자열을 딕셔너리로 다시 역변환하여 사용하는 데는 문제가 없다.
JSON 문자열을 딕셔너리로 변환할 때는 다음처럼 json.loads() 함수를 사용한다.
한글 문자열이 아스키 형태의 문자열로 변경되는 것을 방지하는 방법도 있다.
이처럼 ensure_ascii=False 옵션을 사용하면된다.이 옵션은 데이터를 저장할 때 아스키 형태로 변환하지 않겠다는 뜻이다.
출력되는 JSON 문자열을 보기 좋게 정렬하려면 다음처럼 indent 옵션을 추가하면 된다.
그리고 딕셔너리 외에 리스트나 튜플처럼 다른 자료형도 JSON 문자열로 바꿀 수 있다.
urllib
urllib 은 URL을 읽고 분석할 때 사용하는 모듈이다.
브라우저로 위키독스의 특정 페이지를 읽으려면 다음과 같이 요청하면 된다.
URL을 호출하여 원하는 리소스를 얻으려면 urllib 모듈을 사용해야 한다.
get_wikidocs(page)는 위키독스의 페이지 번호를 입력받아 해당 페이지의 리소스 내용을 파일로 저장하는 함수다.
이 코드에서 보듯이 urllib.request.urlopen(resource)로 s 객체를 생성하고 s.read() 로 리소스 내용 전체를 읽어
이를 저장할 수 있다.
webbrowser
webbrowser는 파이썬 프로그램에서 시스템 브라우저를 호출할 때 사용하는 모듈이다.
파이썬으로 웹 페이지를 새 창으로 열려면 webbrowser 모듈의 open_new() 함수를 사용해야 한다.
이미 열린 브라우저로 원하는 사이트를 열고 싶다면 다음처럼 open_new() 대신 open() 사용하면 된다.
05-7 외부 라이브러리
파이썬 표준라이브러리: 파이썬 설치 시 기본으로 설치되는 라이브러리
외부 라이브러리: 표준 라이브러리와 달리 따로 설치해줘야 사용할 수 있는 라이브러리
pip: 파이썬 모듈패키지나 패키지를 쉽게 설치할 수 있는 도구로, 의존성있는 패키지 등을 설치할때 유용하다. (설치 규칙에 따라서 입력하지 않은 패키지도 자동으로 설치해주는 기능이 있다.)
<<pip명령어 모음>>
pip install (패키지 이름) #pip으로 패키지 설치
pip install (패키지이름) == (버전) #패키지의 버전까지도 지정해 설치할 수 있다.
#버전 생략시 최신버전으로 설치된다.
pip uninstall (패키지 이름) #pip으로 설치한 패키지 삭제
pip install --upgrade (패키지 이름) #설치한 패키지 최신버전 업데이트
pip list #설치된 패키지 목록 출력
pip을 이용한 외부 라이브러리 설치
1)Faker: 테스트용 가짜 데이터를 생성할 때 이용되는 외부 라이브러리
#입력
pip install Faker
from faker import Faker
fake = Faker()
fake.name()
#출력
'Tiffany Chen'
#입력
test_data = [(fake.name(), fake.address()) for i in range(30)]
print(test_data)
#[(이름1, 주소1), (이름2, 주소2), ..., (이름n, 주소n)] 과 같은 형태의 n개의 데이터를 생성할 수 있음
#출력
[('전서준', '세종특별자치시 강북구 테헤란거리'), ('안성호', '경기도 수원시 장안구 서초중앙07거리 (미경박이읍)'), ('손성훈', '광주광역시 동대문구 영동대길 (시우오마을)'), ('이수빈', '서울특별시 구로구 학동466가 (유진안읍)'), ('장건우', '강원도 수원시 장안구 강남대347거리'), ('강지훈', '전라남도 화성시 반포대0가'), ('민미영', '세종특별자치시 은평구 가락358가'), ('김상현', '경기도 청주시 서원구 영동대07가 (수민박동)'), ('노혜진', '서울특별시 서대문구 영동대로'), ('백유진', '대전광역시 강동구 테헤란거리 (혜진박마을)'), ('유성훈', '전라북도 파주시 삼성길'), ('김영환', '경상북도 가평군 서초중앙6거리 (지현서이마을)'), ('이준서', '서울특별시 강서구 영동대27로'), ('안숙자', '울산광역시 관악구 개포가'), ('박예원', '울산광역시 마포구 삼성25로'), ('최정순', '경상북도 공주시 삼성가 (은서박면)'), ('구미영', '광주광역시 마포구 양재천419거리'), ('류승현', '강원도 단양군 가락064가 (영일이이리)'), ('정선영', '경상북도 시흥시 선릉거리'), ('배민재', '경상북도 부천시 원미구 논현2길 (동현김마을)'), ('이서현', '서울특별시 서대문구 논현048가 (영호서안동)'), ('박서윤', '대구광역시 금천구 선릉491로 (정순손마을)'), ('박승민', '충청남도 의정부시 양재천36길 (도윤전김리)'), ('이병철', '세종특별자치시 금천구 선릉로'), ('이주원', '전라북도 화성시 석촌호수거리'), ('이수빈', '제주특별자치도 평택시 역삼가'), ('홍예원', '서울특별시 서구 도산대96거리'), ('김정남', '전라북도 계룡시 서초대173가'), ('남보람', '경상남도 음성군 압구정62로 (승민송고읍)'), ('오순자', '강원도 군포시 도산대58가 (유진안동)')]
+) fake.name()-이름, fake.address()-주소, fake.postcode()-우편번호등 fake를 사용하면 다양한 종류의 테스트 데이터들을 생성할 수 있다!!!
2)sympy: 방정식 기호(symbol)를 사용하게 해주는 외부 라이브러리
sympy.symbols(): x처럼 방정식에 사용하는 미지수를 나타내는 기호를 생성하는 함수
* x, y = sympy.symbols('x y')처럼 여러개의 미지수를 설정할 수도 있다.
#sympy.Eq(a, b): a와b가같다는방정식
#sympy를 이용한 방정식 풀이2
from fractions import Fraction
import sympy
x,y = sympy.symbols("x y")
f1 = sympy.Eq(x+2*y, 10)
f2 = sympy.Eq(6*x-y, 4)
sympy.solve([f1, f2]) #연립방정식도 해결할 수있으나, 이 경우 일차방정식과는 달리 결과값이 딕셔너리의 형태로 저장된다는 점에서 차이가 있다.
3주차 Python study 퀴즈