파이썬에서는 queue모듈에서 큐(Queue), 우선순위큐(PriorityQueue), 스택(LifoQueue)을 제공하고 있다. 특히 큐 모듈은 스레드환경을 고려하여 작성되었기에, 여러 스레드들을 동시에 큐객체(queue모듈에서 제공되는 3개의 클래스를 지칭)에 데이터를 입력하고, 데이터를 출력하여도 정상적으로 작동하는것을 보장한다.
파이썬에서는 Queue 자료구조를 손쉽게 활용할 수 있는 모듈을 제공한다.
Queue : FIFO(First In, First Out), 먼저 들어간 데이터가 먼저 나오는 구조.
Stack : LIFO(Last In, First Out), 마지막에 들어간 데이터가 먼저 나오는 구조.
import queue
선입선출(FIFO First-In, First-Out)큐 객체를 생성
queue.Queue(maxsize)
q = queue.Queue()
q
>>> <queue.Queue object at 0x1019ad6d0>
# maxsize 지정
q2 = queue.Queue(14)
queue.put(item[,block[,timeout]])
block은 블로킹 유무, timeout은 블로킹이 될 시간을 초단위로 입력할 수 있다.
블로킹은 큐 객체가 꽉 찬 경우, queue.Full예외를 발생시킬 수 있다.
q.put(1)
a = queue.Queue(2)
a.put(1)
a.put(2)
a.full()
>>> True
a.put(3) # 다른 스레드가 아이템을 가지고 갈 때까지 무한 대기
a.put(3, True, 5) # 5초 후 queue.Full예외 발생
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/nam/miniconda3/lib/python3.7/queue.py", line 147, in put
raise Full
queue.Full
a.put(3, False) # 바로 queue.Full예외 발생
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/nam/miniconda3/lib/python3.7/queue.py", line 136, in put
raise Full
queue.Full
queue.put_nowait(item)
블로킹없이 큐 객체에 아이템을 입력한다. 큐 객체가 꽉 차 있는 경우에는 queue.Full예외 발생.
그냥 큐객체가 꽉 차있을 때 put()메소드를 쓰면 무한대기하는 상황이 생기는데, 이 상황을 피하고자 put_nowait() 메소드를 지원한다.
queue.get([block[,timeout]])
생성된 큐 객체 특성에 맞추어, 아이템 1개를 반환.
q.get()
>>> 2
q.empty()
>>> True
q.get() # 무한 대기
q.get(False)
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/nam/miniconda3/lib/python3.7/queue.py", line 167, in get
raise Empty
_queue.Empty
queue.get_nowait()
큐 객체가 비어있는 경우에 queue.Empty예외 발생.
그냥 큐 객체가 비어있을 때 get()메소드를 쓰면 무한대기하는 상황이 생기는데, 이 상황을 피하고자 get_nowait() 메소드를 지원한다.
q.get_nowait()
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/nam/miniconda3/lib/python3.7/queue.py", line 198, in get_nowait
return self.get(block=False)
File "/Users/nam/miniconda3/lib/python3.7/queue.py", line 167, in get
raise Empty
_queue.Empty
queue.qsize()
q.put('a')
q.put('b')
q.put('c')
q.qsize()
>>> 3
queue.Empty
큐 객체에 아이템이 없는 경우 발생. empty()메소드로 비어있는지 체크 가능.
q.empty()
>>> True
queue.Full
큐 객체에 아이템이 꽉 찬 경우에 발생. full()메소드로 꽉 찼는지 체크 가능.
큐 선언할 때 maxsize를 지정했을 경우 true, false 판단 가능
q.full()
>>> False
일반적으로 스택(Stack)이라 불리는 후입선출(LIFO Last-In, First-Out)큐 객체를 생성
queue.LifoQueue(maxsize)
q = queue.LifoQueue()
q1 = queue.LifoQueue(2)
q2 = qeueue.LifoQueue(maxsize=2)
삽입 queue.put(item[,block[,timeout]])
조회 queue.get([block[,timeout]])
q.put('c')
q.put('b')
q.put('a')
q.get()
>>> 'a'
q.get()
>>> 'b'
q.get()
>>> 'c'
우선순위 큐는 데이터를 추가한 순서대로 제거하는 선입선출(FIFO) 특성을 가진 일반적인 큐의 자료구조와 달리, 데이터 추가는 어떤 순서로 해도 상관이 없지만, 제거될 때는 가장 작은 값을 제거하는 독특한 특성을 지닌 자료구조이다.
queue.PriorityQueue(maxsize)
q = queue.PriorityQueue()
q1 = queue.PriorityQueue(2)
q2 = queue.PriorityQueue(maxsize=2)
queue.put((priority_number, data))
queue.get([block[,timeout]])
우선순위큐에서는 일반적으로 (priority_number, data) 형식의 튜플형태로 넣는다. 인덱스로 data에 접근가능하다.
q.put((2,'banana'))
q.put((1,'apple'))
q.put((3,'candy'))
q.get()
>>> (1, 'apple')
q.get()
>>> (2, 'banana')
q.get()[1]
>>> 'candy'
같은 우선순위가 있을 때는 내부적으로 우선순위를 정하여 반환하는 것 같다.
아래의 예를 보면 bye
가 먼저 들어갔음에도 불구하고 bae
가 먼저 반환된다.
c.put((2,'bye'))
c.put((1,'apple'))
c.put((2,'bae'))
c.get()
>>> (1, 'apple')
c.get()
>>> (2, 'bae')
c.get()
>>> (2, 'bye')
우선순위를 줄 때 마이너스-도 가능하다.
아래 링크에서 나의코드2 참고
예제 바로가기
queue.put(item[,block[,timeout]])
그냥 일반적인 큐처럼 넣을 수도 있다. 하지만 내부적으로 우선순위를 정하여 조회할 때 우선순위가 높은 것부터 반환한다.
q = queue.PriorityQueue()
q.put(4)
q.put(1)
q.put(3)
q.get()
>>> 1
q.get()
>>> 3
q.get()
>>> 4