2015-05-18 12 views
7

Nếu tôi sử dụng Queue.Queue, thì chức năng read() của tôi không hoạt động, tại sao? Nhưng nếu tôi sử dụng multiprocessing.Queue, nó hoạt động tốt:multiprocessing.Queue và Queue.Queue là khác nhau?

from multiprocessing import Pool, Process, Queue 
import os, time 
# from Queue import Queue 

def write(q): 
    for v in ['A', 'B', 'C']: 
     print 'Put %s to queue ' % v 
     q.put_nowait(v) 
     time.sleep(0.2) 

def read(q): 
    while 1: 
     if not q.empty(): 
      v = q.get(True) 
      print "Get %s from queue" % v 
      time.sleep(0.2) 
     else: 
      break 

if __name__ == '__main__': 
    q = Queue() 
    pw = Process(target=write, args=(q,)) 
    pr = Process(target=read, args=(q,)) 
    pw.start() 
    pw.join() 

    pr.start() 
    pr.join() 

    print "all done..." 
+2

Hãy suy nghĩ về nó theo cách này: nếu chúng _wer't_ khác nhau, tại sao 'multiprocessing.Queue' thậm chí tồn tại? Toàn bộ điểm của nó là cung cấp cho bạn một đối tượng giống như 'queue.Queue' cũng hoạt động giữa các tiến trình riêng biệt. – abarnert

Trả lời

19

Queue.Queue chỉ là một hàng đợi trong bộ nhớ mà biết làm thế nào để đối phó với nhiều chủ đề sử dụng nó cùng một lúc. Nó chỉ hoạt động nếu cả nhà sản xuất và người tiêu dùng đều trong cùng một quy trình.

Khi bạn có chúng trong các quy trình hệ thống riêng biệt, đó là thư viện multiprocessing, mọi thứ phức tạp hơn một chút, vì các quy trình không còn chia sẻ cùng một bộ nhớ nữa. Bạn cần một loại phương pháp giao tiếp liên ngành để cho phép hai tiến trình nói chuyện với nhau. Nó có thể là một bộ nhớ chia sẻ, một đường ống hoặc một ổ cắm, hoặc có thể là một cái gì đó khác. Đây là những gì multiprocessing.Queue làm. Nó sử dụng đường ống để cung cấp một cách cho hai quy trình để giao tiếp. Nó chỉ xảy ra để thực hiện cùng một API như Queue.Queue, bởi vì hầu hết các lập trình viên Python đã quen thuộc với nó.

Cũng lưu ý rằng cách bạn đang sử dụng hàng đợi, bạn có điều kiện chủng tộc trong chương trình của mình. Hãy suy nghĩ về những gì sẽ xảy ra nếu quy trình write ghi vào hàng đợi ngay sau khi bạn gọi q.empty() trong quy trình read. Thông thường, bạn sẽ thêm một số mặt hàng đặc biệt vào hàng đợi (ví dụ: None) có nghĩa là người tiêu dùng có thể dừng lại.

+0

Tôi đã tìm thấy q.empty() cho Multiprocessing.Queue được * cực kỳ * không đáng tin cậy. Đó là sai thường xuyên hơn nó đúng, thẳng thắn. Thậm chí không có vấn đề về điều kiện chủng tộc: bạn có thể có Process A dính thứ gì đó vào hàng đợi khi Process B đang ngủ, và sau đó gọi empty() từ Process B - nó báo cáo rỗng, cho dù mục đó có đợi bao lâu. Một lựa chọn tốt hơn là kiểm tra xem qsize()> 0 - không hoàn hảo, nhưng * nhiều * liên tục chính xác hơn. –

+0

Một FYI liên quan đến đa xử lý.Queue (như là một sự khác biệt hành vi trên hàng đợi.Queue): Dữ liệu được chèn vào hàng đợi * phải * được đọc. Nếu một tiến trình ghi vào một hàng đợi và sau đó kết thúc, nó sẽ không thực sự chấm dứt cho đến khi một tiến trình khác lấy được hàng của hàng đợi. –

Các vấn đề liên quan