

์ ๋๋ ์ดํฐ๋ ์ดํฐ๋ ์ดํฐ๋ฅผ ์์ฑํด์ฃผ๋ ํจ์์ด๋ค. ์ ๋๋ ์ดํฐ๋ ํจ์ ์์์ yield ํค์๋๋ง ์ฌ์ฉํ๋ฉด ๋๋ค.
def number_generator():
yield 0
yield 1
yield 2
g = number_generator()
print(g.next()) # 0
print(g.next()) # 1
print(g.next()) # 2
print(g.next()) # StopIteration
์ด๋ฒ ๊ณผ์ ๋ ๋ค์์ฝ๋๋ฅผ ์คํํด๋ณด๊ณ ๋ถ์ํ ๊ฒฐ๊ณผ๋ฅผ ๋ธ๋ก๊น ํ๋ ๊ณผ์ ์ ๋๋ค. lazy evaluation ์ด๋ ๋ฌด์์ธ์ง์ ์ฅ์ ๋ฐ ๋ฆฌ์คํธ ์ปดํ๋ฆฌํจ์ ๊ณผ์ ์ฐจ์ด์ ์ ๋ํ์ฌ ๋ธ๋ก๊น ํด์ฃผ์ธ์
import time
L = [ 1,2,3]
def print_iter(iter):
for element in iter:
print(element)
def lazy_return(num):
print("sleep 1s")
time.sleep(1)
return num
print("comprehension_list=")
comprehension_list = [ lazy_return(i) for i in L ]
print_iter(comprehension_list)
print("generator_exp=")
generator_exp = ( lazy_return(i) for i in L )
print_iter(generator_exp)
lazy evaluation์ ๊ณ์ฐ์ ๋์ค์ผ๋ก ๋ฏธ๋ฃจ๋ ๊ฒ์ ์๋ฏธํ๋ฉฐ ์ด๋ ๋ฉ๋ชจ๋ฆฌ์ ๋ํด์ ์ฅ์ ์ ๊ฐ์ง ์ ์๋ค. ์๋ํ๋ฉด ํจ์๋ฅผ ์คํ์ํจ ํ์ return ๊ฐ์ ํ์ฉํ์ง ์์ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ์ ๋ญ๋น๊ฐ ๋ฐ์ํ๋ค. ๊ทธ๋ฌ๋ ์ ๋๋ ์ดํฐ ํจ์๊ฐ ์คํ๋ ๋๊น์ง ๊ณ์ฐ์ ๋ฏธ๋ฃจ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น๊ฐ ๋ฐ์ํ์ง ์๊ฒ ๋๋ค.
์ฐจ์ด์ ์ ์ค๋ช
ํ๊ธฐ ์ ์ ์์ ์ฝ๋ ์คํ ๊ฒฐ๊ณผ ํ๋ฉด์ ๋ค์๊ณผ ๊ฐ๋ค.

lambda๋ ์ต๋ช ํจ์์ด๋ค.
lambda ๋งค๊ฐ๋ณ์๋ค: ์, ์ธ์
lambda ๋งค๊ฐ๋ณ์๋ค: ์1 if ์กฐ๊ฑด์ else ์2
lambda ๋งค๊ฐ๋ณ์๋ค: ์1 if ์กฐ๊ฑด์1 else ์2 if ์กฐ๊ฑด์2 else ์3
๋ค์ ์ฝ๋๋ฅผ ์คํํด๋ณด๊ณ print๋ฌธ์ผ๋ก ์ถ๋ ฅ๋๋ ์ถ๋ ฅ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ณด๊ณ types ๋ชจ๋์ LambdaType ์ธ์๋ ์ด๋ค ํ์ ๋ค์ด ์๋์ง ์กฐ์ฌํด ๋ณด์ธ์.





์ฐ๋ ๋ ๊ณต์๋ฌธ์์์ ํ์ตํ ๋ด์ฉ์ ๋ํด์ ์์ ๋กญ๊ฒ ๋ธ๋ก๊น (์คํํด๋ณธ ์์ ์ฝ๋๋ฅผ ๋ถ์ํ ๋ด์ฉ์ ๋ธ๋ก๊น ํด๋ ์ข๊ณ ์ด๋ก ์ ์ธ ๋ด์ฉ์ ๋ธ๋ก๊น ํด๋ ์ข์ต๋๋ค.)
import threading
import time
shared_number = 0
def thread_1(number):
global shared_number
print("number = ",end=""), print(number)
for i in range(number):
shared_number += 1
def thread_2(number):
global shared_number
print("number = ",end=""), print(number)
for i in range(number):
shared_number += 1
if __name__ == "__main__":
threads = [ ]
start_time = time.time()
t1 = threading.Thread( target= thread_1, args=(50000000,) )
t1.start()
threads.append(t1)
t2 = threading.Thread( target= thread_2, args=(50000000,) )
t2.start()
threads.append(t2)
for t in threads:
t.join()
print("--- %s seconds ---" % (time.time() - start_time))
print("shared_number=",end=""), print(shared_number)
print("end of main")
threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
shared_number ๊ฐ ์ฒ๋ง์ผ๋ก ์ฆ๊ฐ๋์ง ์๋ ์ด์ ๋ฅผ ์ค๋ช ํ๊ณ ( ๋ธ๋ก๊ทธ ๋๋ ๋ฉํ ์๊ฒ ์ค๋ช )
์์ ์ฝ๋ ๊ธฐ๋ฐ์ผ๋ก ๋๊ฐ์ ์ฐ๋ ๋์์ ๊ฐ๊ฐ 50000000์ฉ ์ฆ๊ฐ์์ผ์ shared_number ๋ฅผ ์ฒ๋ง์ผ๋ก ์ฆ๊ฐ์ํค๋ ์ฝ๋๋ฅผ ๊ตฌํํ๋ ๊ณผ์ ์ ๋๋ค.( hint. ์กฐ๊ฑด๋ณ์, ๋ฎคํ ์ค )
import threading
import time
shared_number = 0
def thread_1(number,cv):
global shared_number
print("number = ",end=""), print(number)
cv.acquire() # Lock์ ํ๋ํ๊ฒ ๋๊ณ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์ ๊ทผํ ์ ์๋๋ก ์ ๊ทผ๋ค.
for i in range(number):
shared_number += 1
cv.release() # Lock์ ํ์ด์ค๋ค. ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์ ๊ทผํ ์ ์๋๋ก ํ๋ค.
def thread_2(number,cv):
global shared_number
print("number = ",end=""), print(number)
cv.acquire() # Lock์ ํ๋ํ๊ฒ ๋๊ณ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์ ๊ทผํ ์ ์๋๋ก ์ ๊ทผ๋ค.
for i in range(number):
shared_number += 1
cv.release() # Lock์ ํ์ด์ค๋ค. ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์ ๊ทผํ ์ ์๋๋ก ํ๋ค.
if __name__ == "__main__":
threads = [ ]
start_time = time.time()
tc = threading.Lock() #Lock ๊ฐ์ฒด ์์ฑ
t1 = threading.Thread( target= thread_1, args=(50000000,tc,) )
t1.start()
threads.append(t1)
t2 = threading.Thread( target= thread_2, args=(50000000,tc,) )
t2.start()
threads.append(t2)
for t in threads:
t.join() # thread๊ฐ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ค๋ค.
print("--- %s seconds ---" % (time.time() - start_time))
print("shared_number=",end=""), print(shared_number)
print("end of main")

import threading
import time
shared_number = 0
def thread_1(number, cv, que):
global shared_number
for _ in range(number):
cv.acquire()
while len(que) < 1:
cv.wait()
que.pop()
shared_number += 1
def thread_2(number, cv, que):
global shared_number
for _ in range(number):
cv.acquire()
que.append(shared_number)
shared_number += 1
cv.notify()
cv.release()
if __name__ == "__main__":
threads = [ ]
que = []
start_time = time.time()
tc = threading.Condition()
t1 = threading.Thread( target= thread_1, args=(50000000,tc,que) )
t1.start()
threads.append(t1)
t2 = threading.Thread( target= thread_2, args=(50000000,tc,que) )
t2.start()
threads.append(t2)
for t in threads:
t.join()
print("--- %s seconds ---" % (time.time() - start_time))
print("shared_number=",end=""), print(shared_number)
print("end of main")
์๋ ์ฐธ๊ณ ์๋ฃ์ธ ํ์ด์ฌ ๊ณต์๋ฌธ์์์ ํ์ตํ ๋ด์ฉ์ ๋ํด์ ์์ ๋กญ๊ฒ ๋ธ๋ก๊น ( ์คํํด๋ณธ ์์ ์ฝ๋๋ฅผ ๋ถ์ํ ๋ด์ฉ์ ๋ธ๋ก๊น ํด๋ ์ข๊ณ ์ด๋ก ์ ์ธ ๋ด์ฉ์ ๋ธ๋ก๊น ํด๋ ์ข์ต๋๋ค.)
from multiprocessing import Process, Queue
import time
def worker(id, number, q):
increased_number = 0
for i in range(number):
increased_number += 1
q.put(increased_number) # put()์ ํตํด Queue ๊ฐ์ฒด์ ๊ฐ์ ๋ฃ๋๋ค.
return
if __name__ == "__main__":
start_time = time.time()
q = Queue() # Queue
th1 = Process(target=worker, args=(1, 50000000, q))
th2 = Process(target=worker, args=(2, 50000000, q))
th1.start()
th2.start()
th1.join()
th2.join()
print("--- %s seconds ---" % (time.time() - start_time))
q.put('exit')
total = 0
while True:
tmp = q.get()
if tmp == 'exit':
break
else:
total += tmp
print("total_number=",end=""), print(total)
print("end of main")
threading์ ์ฌ์ฉํ ๋์ ๊ฑฐ์ ๋์ผํ๋ค.
Pool ํด๋์ค๋ ์์ ์ ํ๋ก์ธ์ค ํ์ ๋ํ๋ธ๋ค.
from multiprocessing import Pool
def f(x):
return x*x
if __name__ = '__main__':
with Pool(processes = 4) as pool:
print(pool.map(f,range(10)))
์์ ์ฝ๋๋ ๋ค์ ์ฝ๋์ ๊ฐ์ ์ฝ๋์ด๋ค.
def f(x):
return x*x
if __name__ = '__main__':
pool = Pool(processes = 4)
print(pool.map(f,range(10)))
ํ๋ก์ธ์ค ์ฌ์ด์ ์์ฌ์ํตํ ์ ์๋ ๋ ๊ฐ์ง ํ์ ์ด ์กด์ฌํ๋ค. Queue์ Pipe๊ฐ ํด๋น๋๋ค.
Queue๋ q.put()์ ํตํด ๊ฐ์ ๋ฃ๊ณ q.get()์ ํตํด ๊ฐ์ ์ป๋๋ค. ์์ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด q์ ๊ฐ๊ฐ์ ์ฆ๊ฐ๋ ์ซ์๋ฅผ ์ ๋ ฅํ๊ณ ๋ง์ง๋ง ๋ถ๋ถ์ while๋ฌธ์ ํตํด tmp์ ๊ฐ์ ๋ด๊ณ total์ ๋ํด์, ์ฆ ๊ฐ๊ฐ 50000000์ ์ซ์๋ฅผ ๋ํด 100000000์ด๋ผ๋ total๊ฐ์ ์ป๊ฒ ๋๋ค.
Pipe๋ ํ ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋๋ฐ ์๋ ์ฝ๋๋ฅผ ๋จผ์ ์ดํด๋ณด์.
from multiprocessing import Process, Pipe
def f(conn):
conn.send([42, None, 'hello'])
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=f, args=(child_conn,))
p.start()
print(parent_conn.recv()) # prints "[42, None, 'hello']"
p.join()
parent_conn๊ณผ child_conn์ด ํ ์์ ์ฐ๊ฒฐ๋ ๊ฐ์ฒด์ด๋ค. ์ฆ child_conn์์ send()๋ฅผ ํตํด ๊ฐ์ ์ ๋ ฅํ๊ณ parent_conn์ ํตํด ๊ฐ์ ์ป๋๋ค. ์ฆ ๊ฐ๊ฐ ์ฐ๊ฒฐ๋ ๊ฐ์ฒด์ด๋ค. ํ์ง๋ง ๊ฐ์ ์ชฝ์์ ์ฝ๊ณ ์ฐ๋ ์์ ์ ๋์์ ์งํํ๋ ค๊ณ ํ๋ค๋ฉด ๋ฐ์ดํฐ์ ์์์ ๋ฐ์์ํฌ ์ ์๋ค.
์์ ์ฝ๋ ๊ธฐ๋ฐ์ผ๋ก ์๋ ํ์ด์ฌ ๊ณต์ ๋ฌธ์๋ฅผ ํ์ตํํ, IPC๋ฐฉ์์ค ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๋ฐฉ์์ผ๋ก ๋๊ฐ์ ํ๋ก์ธ์ค๋ก 50000000์ฉ ์ฆ๊ฐ์ํค๊ณ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ์ธ๋งํฌ์ด๋ก ๋๊ธฐํ ์์ผ ์ต์ข ๊ฐ์ผ๋ก 1์ต์ ๋ง๋๋ ์ฝ๋๋ฅผ ๊ตฌํํด ๋ณด์ธ์.
from multiprocessing import Process, Semaphore, shared_memory
import time
import numpy as np
def worker(id, number, a, s, shm):
increased_number = 0
for i in range(number):
increased_number += 1
s.acquire()
ex_shm = shared_memory.SharedMemory(name=shm)
c = np.ndarray(a.shape, dtype=a.dtype, buffer=ex_shm.buf)
c[0] += increased_number
s.release()
return
if __name__ == "__main__":
start_time = time.time()
a = np.array([0])
shm = shared_memory.SharedMemory(create = True, size = a.nbytes)
b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
s = Semaphore()
th1 = Process(target=worker, args=(0, 50000000, a, s, shm.name))
th2 = Process(target=worker, args=(1, 50000000, a, s, shm.name))
th1.start()
th2.start()
th1.join()
th2.join()
print("--- %s seconds ---" % (time.time() - start_time))
print('exit')
print("total_number=",end=""), print(b[0])
print("end of main")
shm.close()
shm.unlink()
์ด ๋ชจ๋์ ๋ฉํฐ ์ฝ์ด๋ ๋์นญ ๋ฉํฐ ํ๋ก์ธ์ (SMP) ๊ธฐ๊ณ์์ ํ๋ ์ด์์ ํ๋ก์ธ์ค๊ฐ ์ ๊ทผํ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๊ณผ ๊ด๋ฆฌ๋ฅผ ์ํ ํด๋์ค SharedMemory๋ฅผ ์ ๊ณตํฉ๋๋ค.
class multiprocessing.shared_memory.SharedMemory(name=None, create=False, size=0)
Numerical Python์ ์ค์ ๋ง๋ก์จ ๊ณ ์ฑ๋ฅ์ ์์น ๊ณ์ฐ์ ํ๊ธฐ ์ํด ๋ง๋ค์ด์ง C์ธ์ด๋ก ๊ตฌํ๋ python package์ด๋ค. ํ์ด์ฌ์ ์ด์ฉํ ๋ฐ์ดํฐ ๋ถ์์ ํ๊ธฐ ์ํด์๋ pandas ๋ฟ๋ง ์๋๋ผ numpy๋ฅผ ์ตํ์ผ๋ง ๋ณด๋ค ํธ์จ์ ์ธ ๋ฐ์ดํฐ ๋ถ์์ด ๊ฐ๋ฅํ๋ค. ndarray๋ ์ฑ๋ฅํฅ์์ ์ํด ๊ฐ์ ๋ฐ์ดํฐํ์
๋ง์ ์์๋ก ๊ฐ์ง ์ ์๊ณ , ํฌ๊ธฐ ์ญ์ ๊ณ ์ ๋์ด ์๋ค. ๋ง์ฝ ํฌ๊ธฐ๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์๋ก ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋๊ณ ์ด์ ๊ฐ์ ์ญ์ ๋๋ค.
numpy shape(arr.shape): numpy์์๋ ํด๋น array์ ํฌ๊ธฐ๋ฅผ ์ ์ ์๋ค. shape ์ ํ์ธํจ์ผ๋ก์จ ๋ช๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์๋์ง, ๋ช ์ฐจ์์ผ๋ก ์กด์ฌํ๋์ง ๋ฑ์ ํ์ธํ ์ ์๋ค.
numpy ์๋ฃํ(arr.dtype)
๋ถํธ๊ฐ ์๋ ์ ์ int(8, 16, 32, 64)
๋ถํธ๊ฐ ์๋ ์ ์ uint(8 ,16, 32, 54)
์ค์ float(16, 32, 64, 128)
๋ณต์์ complex(64, 128, 256)
๋ถ๋ฆฌ์ธ bool
๋ฌธ์์ด string
ํ์ด์ฌ ์คํ์ ํธ object
์ ๋์ฝ๋ unicode
print(cr.send("morning")) โ good morning
print(cr.send("afternoon")) โ good afternoon
print(cr.send("evening")) โ good evening
import time
def coroutine_test():
greeting = "good "
while True:
text = (yield greeting)
print("text = ",end=""), print(text)
greeting = "good " # ์ด ์ฝ๋๋ฅผ ์ถ๊ฐํจ
greeting += text
if __name__ == "__main__":
cr = coroutine_test()
print("cr=",end=""), print(cr)
next(cr)
time.sleep(2)
print("send 1")
print(cr.send("morning"))
time.sleep(2)
print("send 2")
print(cr.send("afternoon"))
time.sleep(2)
print("send 3")
print(cr.send("evening"))
time.sleep(2)

asyncio ์ ๋ํด์ ํ์ตํ ํ ๋๋ฒ์งธ ์ฝ๋๋ฅผ coroutine ๊ณผ asyncio ๋ฅผ ํ์ฉํ์ฌ ๊ตฌํํด ๋ณด์ธ์.
import time
import asyncio
async def coroutine_test(num, a):
greeting = "good "
await asyncio.sleep(2)
print(f"send {num}")
print("text = ",end=""), print(a)
greeting += a
print(greeting)
if __name__ == "__main__":
L = ["morning","afternoon","evening"]
loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine_test(1, L[0]))
loop.run_until_complete(coroutine_test(2, L[1]))
loop.run_until_complete(coroutine_test(3, L[2]))
loop.close()

์ ๋๋ ์ดํฐ ๊ธฐ๋ฐ ์ฝ๋ฃจํด์ ๋ํ ์ง์์ ํ์ง๋์๊ณ ํ์ด์ฌ 3.10์์ ์ญ์ ๋ ์์ ์
๋๋ค.(๊ณต์ ๋ฌธ์)

์ฝ๋ฃจํด์ ํจ์๊ฐ ์ข
๋ฃ๋์ง ์์ ์ํ์์ ๋ฉ์ธ ๋ฃจํด์ ์ฝ๋๋ฅผ ์คํํ ๋ค ๋ค์ ๋์์์ ์ฝ๋ฃจํด์ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค. ๋ฐ๋ผ์ ์ฝ๋ฃจํด์ด ์ข
๋ฃ๋์ง ์์์ผ๋ฏ๋ก ์ฝ๋ฃจํด์ ๋ด์ฉ๋ ๊ณ์ ์ ์ง๋ฉ๋๋ค.
1๋ฒ์ ํด๋นํ๋ ์ฝ๋๋ก ์๊ฐํ๋ ๊ฒ์ด ํธํ๋ค. while๋ฌธ ์์์ ๋ฌดํํ ๋ฐ๋ณตํ๋ฉด์ yield๋ถ๋ถ์์ ๊ฐ์ด ๋ค์ด์ค๊ธฐ๋ฅผ ๋๊ธฐํ๊ณ ์๋ ์ํฉ์ด๋ค.
1๋ฒ ์ฝ๋์์ next(cr) ๋ถ๋ถ์ด ๊ทธ๋ฆผ์ ์ต์ด ํธ์ถ์ ํด๋นํ๊ณ yield์ ๋๋ฌํ์ ๋ ๊ฐ์ด ๋ค์ด์ค๊ธธ ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ฉ์ธ ๋ฃจํด์์ send๋ฅผ ํตํด ๊ฐ์ ์ ๋ฌ๋ฐ์ผ๋ฉด ๋ค์ ์ฝ๋๋ฅผ ์งํํ๊ณ ๋ค์ yield๋ฅผ ํตํด ๊ฐ์ ๋ด๋ณด๋ด๋ฉด์ ๋ค์ ๋๊ธฐ ์ํ๋ก ๋ค์ด๊ฐ๋ค.
close()๋ฅผ ํตํด ์ฝ๋ฃจํด์ ์ข ๋ฃํ ์ ์๊ณ throw๋ก ์๋ฌ๋ฅผ ๋ฐ์์์ผ ์ข ๋ฃ์ํฌ ์๋ ์๋ค.
yield from์ ์ฝ๋ฃจํด๋ฅผ ์ง์ ํ๋ฉด ํด๋น ์ฝ๋ฃจํด์์ return์ผ๋ก ๋ฐํํ ๊ฐ์ ๊ฐ์ ธ์จ๋ค. ๋ํ ์ฝ๋ฃจํด์์ yield from์ ์ฌ์ฉํ๋ฉด ์ฝ๋ฃจํด ๋ฐ๊นฅ์์ send๋ก ํ์ ์ฝ๋ฃจํด๊น์ง ๊ฐ์ ๋ณด๋ผ ์ ์๋ค. (์๋ ์ฝ๋ ์ฐธ๊ณ )(์ถ์ฒ:ํ์ด์ฌ ์ฝ๋ฉ ๋์ฅ)
def accumulate():
total = 0
while True:
x = (yield) # ์ฝ๋ฃจํด ๋ฐ๊นฅ์์ ๊ฐ์ ๋ฐ์์ด
if x is None: # ๋ฐ์์จ ๊ฐ์ด None์ด๋ฉด
return total # ํฉ๊ณ total์ ๋ฐํ
total += x
def sum_coroutine():
while True:
total = yield from accumulate() # accumulate์ ๋ฐํ๊ฐ์ ๊ฐ์ ธ์ด
print(total)
co = sum_coroutine()
next(co)
for i in range(1, 11): # 1๋ถํฐ 10๊น์ง ๋ฐ๋ณต
co.send(i) # ์ฝ๋ฃจํด accumulate์ ์ซ์๋ฅผ ๋ณด๋
co.send(None) # ์ฝ๋ฃจํด accumulate์ None์ ๋ณด๋ด์ ์ซ์ ๋์ ์ ๋๋
for i in range(1, 101): # 1๋ถํฐ 100๊น์ง ๋ฐ๋ณต
co.send(i) # ์ฝ๋ฃจํด accumulate์ ์ซ์๋ฅผ ๋ณด๋
co.send(None) # ์ฝ๋ฃจํด accumulate์ None์ ๋ณด๋ด์ ์ซ์ ๋์ ์ ๋๋
async/await ๋ฌธ๋ฒ์ผ๋ก ์ ์ธ๋ ์ฝ๋ฃจํด์ asyncio ์์ฉ ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ ๊ธฐ๋ณธ ๋ฐฉ๋ฒ์ ๋๋ค. asyncio ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ง ์ฝ๋ฃจํด์ ๋ค์ดํฐ๋ธ ์ฝ๋ฃจํด์ด๋ผ๊ณ ํ๋ค.
๋จผ์ asyncio๋ async/await ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ๋์์ฑ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. asyncio๋ ๊ณ ์ฑ๋ฅ ๋คํธ์ํฌ ๋ฐ ์น ์๋ฒ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ๋ถ์ฐ ์์ ํ ๋ฑ์ ์ ๊ณตํ๋ ์ฌ๋ฌ ํ์ด์ฌ ๋น๋๊ธฐ ํ๋ ์์ํฌ์ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. asyncio๋ ์ข ์ข IO ๋ณ๋ชฉ์ด๋ฉด์ ๊ณ ์์ค์ ๊ตฌ์กฐํ๋ ๋คํธ์ํฌ ์ฝ๋์ ๊ฐ์ฅ ์ ํฉํฉ๋๋ค.

async def ํจ์์ด๋ฆ():
์ฝ๋
await ํํ์์์ ์ฌ์ฉ๋ ์ ์์ ๋ ์ด์จ์ดํฐ๋ธ ๊ฐ์ฒด๋ผ๊ณ ๋งํฉ๋๋ค. ์ฝ๋ฃจํด, ํ์คํฌ, ํจ์ฒ
ํ์ด์ฌ ์ฝ๋ฃจํด์ ์ด์จ์ดํฐ๋ธ๋ก ๋ค๋ฅธ ์ฝ๋ฃจํด์์ ๊ธฐ๋ค๋ฆด ์ ์๋ค.
import asyncio
async def nested():
return 42
async def main():
nested() # ๊ทธ๋ฅ ํธ์ถ๋ง ํ ์ํ๋ก ์คํ๋์ง๋ ์๋๋ค.
print(await nested()) # nested()๊ฐ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋๋๋ฉด 42๊ฐ ํ๋ฆฐํธ ๋ ์์
asyncio.run(main()) # ๋ฉ์ธ์ ์คํ์์ผ์ nested()๋ฅผ ์คํ์ํค๊ณ 42๋ฅผ ํ๋ฆฐํธ ํจ
ํ์คํฌ๋ ์ฝ๋ฃจํด์ ๋์์ ์์ฝํ๋๋ฐ ์ฌ์ฉ๋๋ค. ์ฝ๋ฃจํด์ด asyncio.create_task()์ ๊ฐ์ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํ์คํฌ๋ก ์ธ์ผ ๋ ์ฝ๋ฃจํด์ ๊ณง ์คํ๋๋๋ก ์๋์ผ๋ก ์์ฝ๋๋ค.
import asyncio
async def nested():
return 42
async def main():
# asyncio.create_task() ํ์คํฌ ๋ง๋ค๊ธฐ ํจ์
task = asyncio.create_task(nested()) # ์์ฝ
await task task๊ฐ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆผ
asyncio.run(main())
Future๋ ๋น๋๊ธฐ ์ฐ์ฐ์ ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ด๋ ํน๋ณํ ์ ์์ค ์ด์จ์ดํฐ๋ธ ๊ฐ์ฒด์ ๋๋ค. Future ๊ฐ์ฒด๋ฅผ ๊ธฐ๋ค๋ฆด ๋, ๊ทธ๊ฒ์ ์ฝ๋ฃจํด์ด Future๊ฐ ๋ค๋ฅธ ๊ณณ์์ ํด๊ฒฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆด ๊ฒ์ ๋ปํฉ๋๋ค. ์ฝ๋ฐฑ ๊ธฐ๋ฐ ์ฝ๋๋ฅผ async/await์ ํจ๊ป ์ฌ์ฉํ๋ ค๋ฉด asyncio์ Future ๊ฐ์ฒด๊ฐ ํ์ํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์์ฉ ํ๋ก๊ทธ๋จ ์์ค ์ฝ๋์์ Future ๊ฐ์ฒด๋ฅผ ๋ง๋ค ํ์๋ ์์ต๋๋ค. ๋๋๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ถ asyncio API์ ์ํด ๋ ธ์ถ๋๋ Future ๊ฐ์ฒด๋ฅผ ๊ธฐ๋ค๋ฆด ์ ์์ต๋๋ค. Future ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ์ ์์ค ํจ์์ ์๋ loop.run_in_executor()์ด๋ค.
async def main():
await function_that_returns_a_future_object()
# this is also valid:
await asyncio.gather(
function_that_returns_a_future_object(),
some_python_coroutine()
)
asyncio.run(coro, *, debug=False)
asyncio.sleep(delay, result=None, *, loop=None)
asyncio.gather(*aws, loop=None, return_exceptions=False)
asyncio.get_running_loop()
asyncio.get_event_loop()
asyncio.set_event_loop(loop)
asyncio.new_event_loop()
loop.run_until_complete(future)
loop.close()