2011-11-17 25 views
12

Xét đoạn mã sau trong ứng dụng WebApp2 của tôi trong Google App Engine:Hiểu kiên trì đối tượng toàn cầu trong Python WSGI apps

count = 0 

class MyHandler(webapp2.RequestHandler): 

    def get(self): 

     global count 
     count = count + 1 
     print count 

Với mỗi refresh của trang, các gia số đếm cao hơn.

Tôi đến từ thế giới PHP, nơi mọi yêu cầu đều là môi trường toàn cầu mới. Những gì tôi hiểu được đang xảy ra ở đây là, bởi vì tôi đang sử dụng cấu hình wsgi cho WebApp2, Python không khởi động một quy trình mới trên mỗi yêu cầu. Nếu tôi đang sử dụng cấu hình cgi, mặt khác, môi trường toàn cầu sẽ tái khởi tạo mỗi lần, như PHP ...

Giả sử ở trên là chính xác (Nếu không, hãy sửa tôi) ...

  1. Làm cách nào để xử lý các tình huống mà tôi muốn biến toàn cầu chỉ tồn tại trong suốt thời gian yêu cầu? Tôi có thể đặt một biến cá thể trong lớp RequestHandler, nhưng những thứ như các mô-đun tiện ích mà tôi nhập khẩu sử dụng các vars toàn cầu cho những thứ như lưu trữ một đối tượng tin nhắn là gì?
  2. Có một số loại kỹ thuật để đặt lại tất cả các biến hoặc để buộc tái tạo lại môi trường không?
  3. Môi trường toàn cầu có tồn tại vô thời hạn hay không tự động đặt lại ở một thời điểm nào đó?
  4. Có bất kỳ GAE cụ thể nào không hoặc việc duy trì toàn cầu wsgi có hoạt động giống nhau trong bất kỳ kịch bản máy chủ nào không?

EDIT:

Dưới đây là một nỗ lực sử dụng ThreadLocal:

count = 0 

mydata = threading.local() 
mydata.count = 0 

class MyHandler(webapp2.RequestHandler): 

    def get(self): 

     global count 
     count = count + 1 
     print count 

     mydata.count = mydata.count + 1 
     print mydata.count 

Đây cũng tăng trên yêu cầu

+0

Có lý do cụ thể nào bạn đang cố gắng lưu trữ dữ liệu chung bên ngoài kho dữ liệu không? Có vẻ như những gì bạn đang cố gắng có thể được thực hiện dễ dàng hơn với một [truy cập bị hỏng] (http://code.google.com/appengine/articles/sharding_counters.html). –

+0

@ Kevin- biến số đó chỉ là một ví dụ - trường hợp thực tế của tôi hoàn toàn khác - tôi chỉ đang cố gắng hiểu phạm vi toàn cầu trong miền ứng dụng. – Yarin

+0

Related [Tại sao giá treo sử dụng StackedObjectProxies thay vì threading.local?] (Http://stackoverflow.com/q/1686768/95735) –

Trả lời

16

Hiểu biết của bạn là chính xác.Nếu bạn muốn biến tồn tại trong suốt thời gian yêu cầu, bạn không nên biến chúng thành các hình tổng quát - biến chúng thành các biến cá thể trên lớp RequestHandler của bạn, được truy cập như self.var. Vì RequestHandler mới được khởi tạo cho mỗi yêu cầu, các biến của bạn sẽ chính xác xung quanh miễn là bạn cần chúng. Các biến toàn cục là tốt nhất nên tránh trừ khi bạn thực sự cần phạm vi toàn cầu (trái ngược với yêu cầu cụ thể).

Cũng lưu ý rằng ứng dụng App Engine của bạn sẽ chạy trên nhiều máy chủ; globals chỉ có thể truy cập vào các yêu cầu bên trong cùng một máy chủ.

+3

điểm tốt về nhiều máy chủ- cảm ơn – Yarin

4

phân tích của bạn về tình hình là chính xác, một ứng dụng web Python là một quá trình chạy dài. Phải mất một thời gian dài để quay lên trình thông dịch Python và không được thực hiện mọi yêu cầu.

Hoàn toàn có thể tạo biến toàn cục khác "theo yêu cầu" khác nhau. Điều này được thực hiện trong rất nhiều khuôn khổ và mọi người dường như thích nó. Cách để làm điều này phụ thuộc vào máy chủ. Hầu hết các máy chủ đều sử dụng "một luồng cho mỗi yêu cầu" và tôi nghĩ GAE cũng hoạt động. Nếu đây là trường hợp bạn có thể sử dụng threadlocal variable. Nếu bạn lo lắng về giá trị này gắn bó giữa các yêu cầu trên chuỗi đó, bạn sẽ cần một số mã quản lý có thể móc vào đầu/cuối của một yêu cầu. WSGI middleware là một nơi tốt cho việc này nếu khung công tác WebApp2 không cung cấp một cách tốt đẹp để làm điều đó.

Nó chỉ là Python và yêu cầu được phân phát theo chủ đề của riêng nó. Từ đó bạn có thể làm những gì bạn muốn. Không có gì trong Python chỉ cần thiết lập lại tất cả các biến toàn cầu, và thường không đảm bảo (đặc biệt là với GAE) rằng quá trình phục vụ yêu cầu của bạn sẽ là cùng một quá trình, nghĩa là các globals của bạn không được sử dụng để duy trì dữ liệu giữa các yêu cầu trừ khi bạn thực sự biết bạn đang làm gì.

Có rất nhiều khung công tác có hỗ trợ tốt cho việc này, vì vậy nếu WebApp2 không thì tôi khuyên bạn nên tìm kiếm ở nơi khác. Python có rất nhiều tùy chọn và nhiều tùy chọn chạy trên GAE.

+0

cảm ơn. Bạn có thể vui lòng xem các chỉnh sửa của tôi- tôi đã thử threading.local(), nhưng số lượng đó tăng lên giống như toàn cầu của tôi. Tôi có triển khai đúng không? – Yarin

+0

Yêu cầu của bạn có khả năng xuất hiện trên cùng một chuỗi. Hầu hết các máy chủ WSGI được thực hiện bằng cách sử dụng một nhóm luồng, do đó, nó không nhất thiết phải là một chuỗi * mới * theo yêu cầu. Tôi không quen thuộc với các hoạt động bên trong của GAE như thế nào các máy chủ ứng dụng WSGI, nhưng đây là những gì tôi mong đợi. –

2

Trong trường hợp câu hỏi đầu tiên của bạn, tôi nghĩ bạn có thể xem xét tính năng webapp2.Request.registry. Đó là một dict để lưu trữ các trường hợp mà các mô-đun khác nhau có thể chia sẻ trong suốt thời gian tồn tại của yêu cầu.

Mặt khác, nó cũng hữu ích webapp2.WSGIApplication.registry. Trong trường hợp này, các cá thể tồn tại giữa các yêu cầu và có thể được chia sẻ (và sử dụng lại) cho bất kỳ ứng dụng nào của bạn cần trong suốt thời gian tồn tại của ứng dụng, tránh tạo các cá thể trên phạm vi toàn cục.

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