2009-10-03 39 views
19

Tôi cần một số Object Pool và thay vì tự thực hiện nó, tôi nghĩ tôi sẽ xem xét thư viện Python đã sẵn sàng và thử nghiệm.Thực hiện Python Mẫu thiết kế đối tượng hồ bơi

Những gì tôi thấy là rất nhiều người khác looking, nhưng không nhận được nhiều câu trả lời thẳng, vì vậy tôi đã đưa nó qua đây để Stack tràn.

Trong trường hợp của tôi, tôi có một số lượng lớn các luồng (sử dụng mô-đun threading), đôi khi cần phải gọi một máy chủ dựa trên SOAP từ xa. Mỗi người có thể thiết lập kết nối riêng của họ với máy chủ, nhưng việc thiết lập một socket và hoàn thành quá trình xác thực là tốn kém (nó được điều chỉnh bởi máy chủ), vì vậy tôi muốn chia sẻ một nhóm kết nối, tạo ra nhiều hơn khi cần thiết.

Nếu các mục vào nhóm là các quy trình phụ của công nhân, tôi có thể đã chọn multiprocessing.pool, nhưng chúng không phải là. Nếu chúng là chủ đề công nhân, tôi có thể đã chọn this implementation, nhưng chúng không phải.

Nếu chúng là các kết nối MySQL, tôi có thể đã chọn pysqlpool, nhưng chúng không phải là. Tương tự, SQLAlchemy Pool đã hết.

Nếu có một chủ đề, sử dụng số lượng kết nối/đối tượng có thể thay đổi, tôi sẽ xem xét this implementation, nhưng tôi cần nó là an toàn chỉ.

Tôi biết tôi có thể thực hiện lại điều này một cách nhanh chóng, nhưng với rất nhiều người đang tìm kiếm, tôi nghĩ câu trả lời chính tắc về Stack Overflow sẽ rất tuyệt.

Trả lời

23

Dường như với tôi, từ mô tả của bạn, rằng những gì bạn cần là một hồ bơi gồm kết nối, không phải của đối tượng. Để đảm bảo an toàn chỉ đơn giản, chỉ cần giữ các kết nối có thể tái sử dụng trong một phiên bản Queue.Queue, gọi nó là pool. Khi một đối tượng khởi tạo một đối tượng bao quanh kết nối, đối tượng sẽ nhận được kết nối qua pool.get() (tự động hóa nó sẽ chờ nó nếu không có kết nối nào sẵn có và khử nó khi kết nối sẵn sàng cho nó); khi đối tượng được thực hiện bằng cách sử dụng kết nối của nó, nó đặt nó trở lại trong hồ bơi qua pool.put.

Có rất ít chức năng có mục đích chung, ngoài những gì Queue.Queue đã cung cấp cho bạn, không có gì ngạc nhiên khi không có mô-đun cung cấp mô-đun nổi tiếng hoặc phổ biến - khó có thể tạo mô-đun phổ biến khi có 6 dòng mã chức năng trong tất cả (ví dụ: để gọi nhà máy kết nối do người dùng cung cấp để điền hàng đợi trước hoặc chỉ trong thời gian tối đa một số số tối đa - không phải là giá trị gia tăng lớn nói chung, dù sao). "Keo dày", dày gói các chức năng cơ bản từ một mô-đun thư viện chuẩn mà không có giá trị gia tăng đáng kể, là một kiến ​​trúc trừ, sau khi tất cả ;-).

+0

Ah, phải, chờ đợi, nếu không có gì khác trong hồ bơi, đó là những gì danh sách thiếu. Tôi nghĩ tôi thông minh với danh sách thay vì xếp hàng, nhưng thực sự rất thông minh. :) –

+0

@Lennart, cũng không có _guarantee_ về an toàn luồng, bạn có thể hoặc không thể gặp sự cố tùy thuộc vào việc triển khai - với Queue.Queue, an toàn luồng của bạn được đảm bảo. –

+0

Python có Hàng đợi an toàn theo chủ đề đã được tích hợp sẵn? Tôi không biết điều đó! Vâng, điều đó sẽ đẩy nhanh quá trình triển khai (mà tôi nghĩ là ngắn gọn, nhưng chủ yếu là suy nghĩ thông qua các vấn đề tương tranh). Xin lỗi, tôi không hiểu sự khác biệt của bạn về "nhóm kết nối" so với "nhóm các đối tượng". Tôi nói rằng tôi muốn "chia sẻ một nhóm các kết nối", nhưng mỗi kết nối được bao bọc trong một đối tượng, vì vậy nó thực sự là một nhóm các đối tượng. Tuy nhiên, sự khác biệt mà tôi đã cố gắng tạo ra là các đối tượng kết nối KHÔNG hoạt động (không giống như multiprocessing.pool.) – Oddthinking

4

Tôi đã có một vấn đề tương tự và tôi phải nói Queue.Queue là khá tốt, tuy nhiên có một phần còn thiếu của câu đố. Lớp sau giúp giải quyết việc bảo đảm đối tượng được đưa trở lại hồ bơi. Ví dụ được bao gồm.

Tôi đã cho phép 2 cách để sử dụng lớp này, với từ khóa hoặc đối tượng đóng gói có hàm hủy. Các từ khóa với được ưa thích, nhưng nếu bạn không thể/không muốn sử dụng nó vì một lý do nào đó (phổ biến nhất là sự cần thiết cho nhiều đối tượng từ nhiều hàng đợi) ít nhất bạn có một tùy chọn. Tuyên bố từ chối trách nhiệm tiêu chuẩn về hàm hủy không được gọi là áp dụng nếu bạn chọn sử dụng phương thức đó.

Hy vọng điều này sẽ giúp ai đó có cùng vấn đề với OP và bản thân tôi.

class qObj(): 
    _q = None 
    o = None 

    def __init__(self, dQ, autoGet = False): 
     self._q = dQ 

     if autoGet == True: 
      self.o = self._q.get() 

    def __enter__(self): 
     if self.o == None: 
      self.o = self._q.get() 
      return self.o 
     else: 
      return self.o 

    def __exit__(self, type, value, traceback): 
     if self.o != None: 
      self._q.put(self.o) 
      self.o = None 

    def __del__(self): 
     if self.o != None: 
      self._q.put(self.o) 
      self.o = None 


if __name__ == "__main__": 
    import Queue 

    def testObj(Q): 
     someObj = qObj(Q, True) 

     print 'Inside func: {0}'.format(someObj.o) 

    aQ = Queue.Queue() 

    aQ.put("yam") 

    with qObj(aQ) as obj: 
     print "Inside with: {0}".format(obj) 

    print 'Outside with: {0}'.format(aQ.get()) 

    aQ.put("sam") 

    testObj(aQ) 

    print 'Outside func: {0}'.format(aQ.get()) 

    ''' 
    Expected Output: 
    Inside with: yam 
    Outside with: yam 
    Inside func: sam 
    Outside func: sam 
    ''' 
+0

Điều duy nhất thiếu IMHO là phương thức '__getattr__' để bạn có thể coi đây là trình bao bọc cho đối tượng được đóng gói – ThatAintWorking

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