-
Notifications
You must be signed in to change notification settings - Fork 1
2.17. 내용정리: 17일차
- 전 세계의 파이썬 사용자들이 만든 유용한 프로그램을 모아 놓은 것이 바로 파이썬 라이브러리이다.
- 라이브러리는 사전적인 의미로 "도서관"이라는 뜻 그대로 원하는 정보를 찾아보는 곳이다.
- 모든 라이브러리를 전부 다 알 필요는 없으며, 어떤 일을 할 때 어떤 라이브러리를 사용해야 한다는 정도만 알면 된다.
- 필요한 라이브러리가 있다면, 라이브러리 문서를 참고해서 사용법을 익히면 된다.
- 따라서 라이브러리를 직접 만드는 경우, 이를 문서화 해놓는 것이 중요하다.
- 모듈(Module) 은 함수와 변수, 클래스를 모아놓은 것을 의미한다.
- 패키지(Package) 는 특정 기능과 관련된 여러 모듈을 하나의 디렉터리 안에 넣어 관리하는 것을 의미한다.
- 라이브러리(Library) 는 여러 패키지와 모듈을 하나의 디렉터리 안에 모아놓은 것을 의미한다.
즉, 모듈을 M , 패키지를 P , 라이브러리를 L 로 정의하여 표현하자면 다음과 같은 관계가 성립한다.
- M ⊂ P 는 참이다.
- 동시에 M1 ∪ M2 ∪ ... = P 는 참이다.
- P ⊂ L 는 참이다.
- 동시에 P1 ∪ P2 ∪ ... = L 는 참이다.
- M ⊂ P 이므로, M ⊂ L 가 성립한다.
- 따라서, ( M , P ) ⊂ L 가 성립한다.
- 동시에 ( M , P ) ∈ L 역시 성립한다.
- 파이썬에서 기본적으로 제공하는 표준 라이브러리들이 존재한다.
- 이 라이브러리들은 파이썬을 설치하면 같이 설치되는 라이브러리들이다.
- 파이썬에서 기본적으로 제공하는 라이브러리가 어떤 것들이 존재하고 어떻게 사용하는지 알아두면 프로그래밍을 할 때 보다 작업이 수월해진다.
- 아래의 라이브러리들은 파이썬에서 자주 사용되고 꼭 알아 두면 좋은 라이브러리를 중심으로 기술한 것이다.
- 파이썬 공식 사이트의 라이브러리 래퍼런스 문서를 참고하면 다양한 라이브러리들을 확인할 수 있다.
- 모든 라이브러리들을 전부 다 알 필요는 없고, 프로그래밍을 하다가 필요한 상황에서만 참고하면 된다.
- 나처럼 파이썬에서 제공하는 라이브러리들 중 자주 사용되고 기본적인 개념들을 익히려면 wikidocs: 파이썬 라이브러리 문서를 참고하면 좋다.
sys 모듈은 파이썬 인터프리터가 제공하는 변수와 함수를 직접 제어할 수 있게 해주는 모듈이다.
sys.argv 는 명령 행에서 인수를 전달한다.
C:/User/iamjjintta>python test.py Hello Python!- 명령 프롬프트 창에서 위의 예시처럼
test.py뒤에 또 다른 값을 함께 넣어 주면sys.argv리스트에 그 값이 추가된다. - 아래의 예시에서
argv_test.py파일은C:/Users/iamjjintta/my_module디렉터리에 저장했다고 가정한다.
# argv_test.py
import sys
print(sys.argv)명령 프롬프트 창에서 cd 명령어를 통해 my_module 디렉터리로 들어간 뒤, python argv_test.py 인자값 과 같이 명령어를 입력하면 아래의 결과를 확인할 수 있다.
C:/Users/iamjjintta>cd my_module
C:/Users/iamjjintta/my_module>python argv_test.py Hello Python!
['argv_test.py', 'Hello', 'Python!']python 명령어 뒤의 모든 것들이 공백을 기준으로 나뉘어서 sys.argv 리스트의 요소가 된다.
sys.exit 는 강제로 스크립트 종료한다.
sys.exit()-
sys.exit는Ctrl+Z나Ctrl+D단축키를 눌러서 대화형 인터프리터를 종료하는 것과 같은 기능을 한다. - 프로그램 파일 안에서 사용하면 프로그램을 중단시킨다.
-
sys.path는 파이썬 모듈들이 저장되어 있는 위치를 나타낸다. - 즉, 이 위치에 있는 파이썬 모듈은 경로에 상관없이 어디에서나 불러올 수 있다.
- 따라서
sys.path는 자신이 만든 모듈을 불러와 사용할 수 있다.
다음은 그 실행 결과이다.
import sys
print(sys.path)결과
['', 'C:\\Windows\\SYSTEM32\\python310.zip', 'c:\\Python310\\DLLs',
'c:\\Python310\\lib', 'c:\\Python310', 'c:\\Python310\\lib\\site-packages']위 예에서 '' 는 현재 디렉터리를 의미한다.
# path_append.py
import sys
sys.path.append('C:/Users/iamjjintta/my_module')- 위와 같이 파이썬 프로그램 파일에서
sys.path.append를 사용해 경로 이름을 추가할 수 있다. - 이렇게 하고 난 후에는
C:/Users/iamjjintta/my_module디렉터리에 있는 파이썬 모듈을 불러와서 사용할 수 있다. - 참고로, 파일 경로를 표시할 때 명령 프롬프트 창에서는
/,\든 상관없지만, 소스 코드 안에서는 반드시/또는\\기호를 사용해야 한다.
pickle 은 객체의 형태를 그대로 유지하면서 파일에 저장하고 불러올 수 있게 하는 모듈이다.
import pickle
data = {1: 'python', 2: 'you need'}
with open('test.txt', 'wb') as file:
pickle.dump(data, file)- 위의 예시에서는
pickle모듈의dump함수를 사용하여 딕셔너리 객체인data를 그대로 파일에 저장하는 방법을 보여 준다. - 다음은
pickle.dump로 저장한 파일을pickle.load를 사용해서 원래 있던 딕셔너리 객체(data) 상태 그대로 불러오는 예이다.
import pickle
with open('test.txt', 'rb') as file:
data = pickle.load(file)
# '{2:'you need', 1:'python'}'이 출력된다.
print(data)참고로, 위의 예시에서는
dict를 사용했지만,pickle모듈을 통해 어떤 자료형이든 저장하고 불러올 수 있다.
os 모듈은 환경 변수나 디렉터리, 파일 등의 OS 자원을 제어할 수 있게 해주는 모듈이다.
-
os.environ은 내 시스템의 환경 변수값을 가지는 객체이며, 환경 변수에 대한 정보를dict객체로 돌려준다. - 시스템은 제각기 다른 환경 변수 값을 가지고 있는데,
os.environ은 현재 시스템의 환경 변수값을 보여 준다.
import os
# 'environ({'PROGRAMFILES': 'C:\\Program Files', 'APPDATA': … })'과 같이 출력된다.
print(os.environ)- 반환된 객체가
dict이기 때문에 다음과 같이 호출할 수 있다. - 다음은 내 컴퓨터 시스템의
PATH환경 변수 내용이다.
import os
# 결과: 'C:\\Users\\iamjjintta\\AppData\\Local\\Programs\\Python\\Python310\\Scripts\\; ...'
print(os.environ['PATH'])os.chdir 를 사용하면 다음과 같이 현재 디렉터리 위치를 변경할 수 있다.
import os
os.chdir('C:/Users/iamjjintta/my_module')os.getcwd 는 현재 자신의 디렉터리 위치를 돌려준다.
import os
# 결과: 'C:\\Users\\iamjjintta\\my_module'
print(os.getcwd())- 시스템 자체의 프로그램이나 기타 명령어를 파이썬에서 호출할 수도 있다.
- 사용하는 방법은
os.system('명령어')와 같이 사용한다. - 다음은 현재 디렉터리의 디렉터리 구조를 출력해주는 시스템 명령어
dir을 실행하는 예이다.
import os
my_dir = os.system('dir')
print(my_dir)os.popen 은 시스템 명령어를 실행한 결과값을 읽기 모드 형태의 파일 객체로 돌려준다.
import os
with os.popen('dir') as file:
print(file.read())- 위에서 기술한
os모듈의 함수 외에도 더 많은 함수들이 존재한다. - 아래는
os모듈에서 제공하는 대표적인 함수들을 표로 나타낸 것이다.
| 함수 | 설명 |
|---|---|
| os.mkdir('디렉터리') | 새로운 디렉터리를 생성한다. |
| os.rmdir('디렉터리') | 디렉터리를 삭제한다. (단, 디렉터리가 비어있어야 삭제가 가능하다.) |
| os.unlink('파일') | 파일을 삭제한다. |
| os.rename(src, dst) |
src 라는 이름의 파일을 dst 라는 이름으로 바꾼다. |
-
shutil모듈은 파일을 복사해 주는 파이썬 모듈이다. - 아래의 예시는
src라는 이름의 파일을dst로 복사하는 예시이다. - 만약
dst가 디렉터리 이름이라면,src라는 파일 이름으로dst디렉터리에 복사하고 동일한 파일 이름이 있을 경우에는 덮어쓴다.
import shutil
shutil.copy('src.txt', 'dst.txt')위 예를 실행해 보면 src.txt 파일과 동일한 내용의 파일이 dst.txt 로 복사되는 것을 확인할 수 있다.
- 가끔 파일을 읽고 쓰는 기능이 있는 프로그램을 만들다 보면 특정 디렉터리에 있는 파일 이름 모두를 알아야 할 때가 있다.
- 이럴 때 사용하는 모듈이 바로
glob모듈이다.
-
glob.glob은 디렉터리 안의 파일들을 읽어서 리스트 타입으로 반환한다. -
*,?등의 특수 기호(이를 메타 문자라고 함)를 써서 원하는 파일만 읽어 들일 수도 있다. - 다음은
C:/Users/iamjjintta/my_module디렉터리에 있는 파일 중 이름이test로 시작하는 파일을 모두 찾아서 읽어 들이는 예시이다.
import glob
# 결과: ['C:/Users/iamjjintta/my_module\\test.py', 'C:/Users/iamjjintta/my_module\\test.txt', 'C:/Users/iamjjintta/my_module\\test2.py', 'C:/Users/iamjjintta/my_module\\test3.py']
print(glob.glob('C:/Users/iamjjintta/my_module/test*'))tempfile 모듈은 파일을 임시로 만들어서 사용할 때 유용한 모듈이다.
tempfile.mkstemp 는 중복되지 않는 임시 파일의 이름을 무작위로 만들어서 돌려준다.
import tempfile
filename = tempfile.mkstemp()
# 결과: 'C:\WINDOWS\TEMP\~-275151-0'
print(filename)-
tempfile.TemporaryFile은 임시 저장 공간으로 사용할 파일 객체를 돌려준다. - 이 파일은 기본적으로 바이너리 쓰기 모드(
wb)를 갖는다. -
close메서드가 호출되면 이 파일 객체는 자동으로 사라진다.
import tempfile
f = tempfile.TemporaryFile()
f.close()time 은 시간과 관련된 모듈이다.
-
time.time은 UTC(Universal Time Coordinated; 협정 세계 표준시) 를 사용하여 현재 시간을 실수 형태로 반환하는 함수이다. - 1970년 1월 1일 0시 0분 0초를 기준으로 지난 시간을 초 단위로 반환한다.
import time
t = time.time()
print(t)time.localtime 은 time.time 이 반환한 실수 값을 사용해서 연도, 월, 일, 시, 분, 초, ... 의 형태로 바꾸어 주는 함수이다.
import time
t = time.time()
localtime = time.localtime(t)
print(localtime)time.asctime 은 위의 time.localtime 에 의해서 반환된 튜플 형태의 값을 인수로 받아서 날짜와 시간을 알아보기 쉬운 형태로 반환하는 함수이다.
import time
t = time.time()
localtime = time.localtime(t)
asctime = time.asctime(localtime)
print(asctime)-
time.asctime을time.ctime()로 사용해 간편하게 표시할 수 있다. -
asctime과 다른 점은ctime은 항상 현재 시간만을 돌려준다는 점이다.
import time
ctime = time.ctime()
print(ctime)-
time.strftime함수는 시간에 관계된 것을 세밀하게 표현하는 여러 가지 포맷 코드를 제공한다. - 사용하는 방식은
time.strftime('출력할 형식 포맷 코드', time.localtime(time.time()))와 같이 사용한다.
아래는 시간에 관례된 것을 표현하는 포맷 코드를 표로 나타낸 것이다.
| 포맷 코드 | 설명 | 예 |
|---|---|---|
| %a | 요일 줄임말 | Mon |
| %A | 요일 | Monday |
| %b | 달 줄임말 | Jan |
| %B | 달 | January |
| %c | 날짜와 시간을 출력함 | 06/01/01 17:22:21 |
| %d | 날(day) | [01,31] |
| %H | 시간(hour)-24시간 출력 형태 | [00,23] |
| %I | 시간(hour)-12시간 출력 형태 | [01,12] |
| %j | 1년 중 누적 날짜 | [001,366] |
| %m | 달 | [01,12] |
| %M | 분 | [01,59] |
| %p | AM or PM | AM |
| %S | 초 | [00,59] |
| %U | 1년 중 누적 주-일요일을 시작으로 | [00,53] |
| %w | 숫자로 된 요일 | [0(일요일),6] |
| %W | 1년 중 누적 주-월요일을 시작으로 | [00,53] |
| %x | 현재 설정된 로케일에 기반한 날짜 출력 | 06/01/01 |
| %X | 현재 설정된 로케일에 기반한 시간 출력 | 17:22:21 |
| %Y | 년도 출력 | 2001 |
| %Z | 시간대 출력 | 대한민국 표준시 |
| %% | 문자 %
|
% |
| %y | 세기부분을 제외한 년도 출력 | 01 |
아래는 time.strftime 을 사용하는 예시이다.
import time
# 결과: '03/25/22'
print(time.strftime('%x', time.localtime(time.time())))
# 결과: 'Fri Mar 25 09:26:22 2022'
print(time.strftime('%c', time.localtime(time.time())))-
time.sleep은 초(seconds) 단위로 잠시 멈추는 함수이다. -
time.sleep함수는 주로 루프 안에서 많이 사용한다. -
time.sleep함수를 통해 일정한 시간 간격을 두고 루프를 실행할 수 있다.
import time
for i in range(10):
print(i)
time.sleep(1)- 위의 예시는 1초 간격으로
0부터9까지의 숫자를 출력한다. - 위의 예시에서 볼 수 있듯,
time.sleep함수의 인수는 실수 형태를 쓸 수 있다. - 즉,
1이면 1초,0.5면 0.5초가 되는 것이다.
calendar 모듈은 파이썬에서 달력을 볼 수 있게 해주는 모듈이다.
calendar.calendar(연도) 로 사용하면 그해의 전체 달력을 볼 수 있다.
import calendar
print(calendar.calendar(2022))결과
2022
January February March
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 1 2 3 4 5 6 1 2 3 4 5 6
3 4 5 6 7 8 9 7 8 9 10 11 12 13 7 8 9 10 11 12 13
10 11 12 13 14 15 16 14 15 16 17 18 19 20 14 15 16 17 18 19 20
17 18 19 20 21 22 23 21 22 23 24 25 26 27 21 22 23 24 25 26 27
24 25 26 27 28 29 30 28 28 29 30 31
31
April May June
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 1 1 2 3 4 5
4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12
11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19
18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26
25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30
30 31
July August September
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 1 2 3 4 5 6 7 1 2 3 4
4 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11
11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18
18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25
25 26 27 28 29 30 31 29 30 31 26 27 28 29 30
October November December
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 1 2 3 4 5 6 1 2 3 4
3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11
10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18
17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25
24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31
31
calendar.prcal(연도) 를 사용해도 위와 똑같은 결과값을 얻을 수 있다.
import calendar
print(calendar.prcal(2022))-
calendar.prmonth는 해당 년도의 월에 해당하는 달력을 반환한다. - 아래의 예시는 2022년 12월의 달력을 출력하는 예시이다.
import calendar
print(calendar.prmonth(2022, 12))결과
December 2022
Mo Tu We Th Fr Sa Su
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
-
calendar.weekday는 그 날짜에 해당하는 요일 정보를 돌려준다. - 월요일은
0, 화요일은1, 수요일은2, 목요일은3, 금요일은4, 토요일은5, 일요일은6이라는 값을 돌려준다.
import calendar
# '5'가 출력된다.
print(calendar.weekday(2022, 12, 31))위의 예시에서 5 가 출력되었으므로, 2022년 12월 31일은 5 에 해당하는 토요일임을 보여 준다.
calendar.monthrange 함수는 입력받은 달의 1일이 무슨 요일인지와 그 달이 며칠까지 있는지를 튜플 형태로 돌려준다.
import calendar
# 결과값: (3, 31)
print(calendar.monthrange(2015,12))위의 예시에서 (3, 31) 이 출력되었으므로, 2022년 12월 1일은 목요일이고, 이 달은 31일까지 있다는 것을 보여 준다.
random 모듈은 난수(규칙이 없는 임의의 수)를 발생시키는 모듈이다.
random.random 은 0 과 1 사이의 실수 중에서 난수값을 반환한다.
import random
# 결과값: 0.18471036143699138
print(random.random())-
random.randint은 첫 번째 값과 마지막 값 사이의 정수를 반환한다. - 아래의 예시에서는
1에서10사이의 정수 중에서 난수값을 발생시키는 예시이다.
import random
# 결과값: 3
print(random.randint(1, 10))- 아래는
random.randint을 활용한 함수random_pop를 정의한 것이다. - 아래에서 정의한 함수
random_pop은 리스트의 요소 중에서 무작위로 하나를 선택하여 꺼낸 다음 그 값을 돌려준다. - 그 다음, 꺼낸 요소는
pop메서드에 의해 사라진다.
import random
def random_pop(data):
number = random.randint(0, len(data) - 1)
return data.pop(number)
if __name__ == '__main__':
data = [1, 2, 3, 4, 5]
while data:
print(random_pop(data))결과
2
3
1
5
4
-
random.choice는 입력으로 받은 리스트에서 무작위로 하나를 선택하여 반환한다. - 위의 예시에서 정의한 함수
random_pop은random모듈의choice함수를 사용하여 다음과 같이 좀 더 직관적으로 만들 수도 있다.
def random_pop(data):
number = random.choice(data)
data.remove(number)
return numberrandom.shuffle 는 이터레이터 객체의 항목을 무작위로 섞어서 반환해준다.
import random
data = [1, 2, 3, 4, 5]
random.shuffle(data)
# 결과: [5, 1, 3, 4, 2]
print(data)위의 예시에서 리스트 [1, 2, 3, 4, 5] 가 shuffle 함수에 의해 무작위로 섞여서 [5, 1, 3, 4, 2] 로 변한 것을 확인할 수 있다.
-
webbrowser모듈은 자신의 시스템에서 사용하는 기본 웹 브라우저를 자동으로 실행하는 모듈이다.
-
webbrowser.open은 웹 브라우저가 이미 실행된 상태라면 입력 주소로 이동한다. - 만약 웹 브라우저가 실행되지 않은 상태라면 새로 웹 브라우저를 실행한 후 해당 주소로 이동한다.
- 아래는 웹 브라우저를 자동으로 실행하고 해당 URL인
google.com페이지로 이동하는 예시이다.
import webbrowser
webbrowser.open('http://google.com')webbrowser.open_new 은 이미 웹 브라우저가 실행된 상태이더라도 새로운 창으로 해당 주소가 열리게 한다.
import webbrowser
webbrowser.open_new('http://google.com')threading 모듈은 한 프로세스에서 2가지 또는 그 이상의 일을 동시에 수행할 수 있게 하는 모듈이다.
- 컴퓨터에서 동작하고 있는 프로그램을 프로세스(Process) 라고 한다.
- 보통 1개의 프로세스는 한 가지 일만 하지만, 쓰레드(Thread) 를 사용하면 한 프로세스 안에서 2가지 또는 그 이상의 일을 동시에 수행할 수 있다.
- 즉, 병렬 처리를 위한 기법이라고 할 수 있다.
-
threading.Thread은 쓰레드 객체를 사용하기 위한Thread클래스이다. - 인자값으로
target과args를 지정해서 사용해야 한다.- 매개 변수
target은 실행할 함수를 의미한다. - 매개 변수
args는target에 필요한 인자값이며,tuple타입으로 넘겨야 한다. - ex.
threading.Thread(target=함수명, args=(인자값1, 인자값2, ...))
- 매개 변수
아래의 예시는 time.sleep 을 통해 5초간 대기하는 함수 long_task 를 정의한 예시이다.
import time
# 5초의 시간이 걸리는 함수
def long_task():
for i in range(5):
# 1초간 대기한다.
time.sleep(1)
print(f'working: {i}s')
print('Start')
# 함수 'long_task'를 5회 호출한다.
for i in range(5):
long_task()
print('End')- 위에서 정의한 함수
long_task은 수행하는 데 5초의 시간이 걸리는 함수이다. - 위 프로그램은 이 함수를 총 5번 반복해서 수행하는 프로그램이다.
- 이 프로그램은 5초가 5번 반복되니 총 25초의 시간이 걸린다.
- 하지만 앞에서 설명했듯이 스레드를 사용하면 5초의 시간이 걸리는 함수
long_task를 동시에 실행할 수 있으니 시간을 줄일 수 있다.
- 쓰레드 객체를 생성한 후에는
쓰레드_객체.start메서드를 호출하여 쓰레드를 실행한다. -
start메서드는 쓰레드 객체의run메서드를 호출해주는 메서드이다. - 그리고
run메서드는target을 호출하는 메서드이다. - 즉, 실행 순서는
start -> run -> target에 정의한 함수순으로 호출된다.
아래는 위의 예시를 쓰레드로 활용한 예시이다.
import time
import threading
# 5초의 시간이 걸리는 함수
def long_task():
for i in range(5):
# 1초간 대기한다.
time.sleep(1)
print(f'working: {i}s')
print('Start')
threads = []
for i in range(5):
# 쓰레드 객체를 생성한다.
t = threading.Thread(target=long_task)
threads.append(t)
for t in threads:
# 'start' 메서드로 쓰레드를 실행한다.
t.start()
print('End')- 이와 같이 프로그램을 수정하고 실행해 보면 25초 걸리던 작업이 5초 정도에 수행되는 것을 확인할 수 있다.
-
threading.Thread을 사용하여 만든 쓰레드 객체가 동시 작업을 가능하게 해주기 때문이다. - 하지만 위 프로그램을 실행해 보면
Start와End가 먼저 출력되고, 그 이후에 쓰레드의 결과가 출력되는 것을 확인할 수 있다. - 그리고 프로그램이 정상 종료되지 않는다.
- 프로그램으로부터 기대하는 것은
Start가 출력되고 그다음에 쓰레드의 결과가 출력된 후 마지막으로End가 출력되는 것이다.
이 문제를 해결하기 위해서는 다음과 같이 프로그램을 수정해야 한다.
쓰레드 객체의 join 메서는 해당 쓰레드가 완전히 종료될 때까지 기다리게 한다.
import time
import threading
# 5초의 시간이 걸리는 함수
def long_task():
for i in range(5):
# 1초간 대기한다.
time.sleep(1)
print(f'working: {i}s')
print('Start')
threads = []
for i in range(5):
t = threading.Thread(target=long_task)
threads.append(t)
for t in threads:
t.start()
for t in threads:
# 'join' 메서드로 쓰레드가 종료될때까지 기다린다.
t.join()
print('End')위와 같이 join 메서드를 사용하면 원하던 결과를 볼 수 있게 된다.