2013-10-23 5 views
9

Web uygulamamı oluşturmak için Flask kullanıyorum ve bir istemden daha uzun süren bir uzak hizmete bağlantıyı temsil eden global bir kaynak kaydetmek istiyorum (bu durumda, bağlantı 30 güne kadar geçerli olan bir SOAP bağlantısıdır).Flask uzun süredir global kaynaklar

Başka bir örnek, sürücüde bağlantı havuzunu işleyen ve her istekte yeni bir bağlantı oluşturduysanız kötü performans gösteren MongoDB gibi bir veritabanı olabilir.

Ne Uygulama Bağlaması ne de İstek İçeriği bu görev için uygun görünmüyor.

"Pass another object to the main flask application" sorusu, bu kaynakları app.config sözlüğünde depoladığımızı gösterir.

+1

Uygulama içeriği neden uygun görünmüyor? – delnan

+0

Bu alandaki belgeleri kafa karıştırıcı buluyorum. Bu bağlantıların uygulama oluşturma zamanında kurulumunu yapmak istiyorum, ancak API'nın bunu yapmasının bir yolunu bulamıyorum. Bir örnek verebilir misiniz? – idbentley

+1

Uygulama içeriğini kullanın. Gördüğünüz tam kullanım durumu [docs] (http://flask.pocoo.org/docs/appcontext/) –

cevap

3

Uygulamanızın örneklenmesi ile uyuşması ZORUNLU ise, Flask alt sınıfını kullanmalısınız. Uygulamanın oluşturulması bir süreçtir göz önünde bulundurulduğunda, tüm yaptığınız şey nesnelere bir kaynak ekliyorsa bu gerçekten bir şey yapmaz. Gerçek şu ki, uygulamanın kaynağınız sırasında kaynağınızı kullanması gerekmiyorsa muhtemelen bunu yapmanız gerekmez. Eğer bazı özel kullanım durumunda yoksa

class MyApp(Flask): 
    def __init__(self, *args, **kwargs): 
     setattr(self, 'some_resource', SomeResource()) 
     super(Flask, self).__init__(*args, **kwargs) 

app = MyApp(__name__) 
app.some_resource.do_something() 

, modül düzeyinde oluşturduktan ve app.extensions üzerinde saklayarak, muhtemelen bir şişe-uzantısına dönüştürerek, bir sarmalayıcı sınıf yazma daha iyi. Sonra

class MyExtensions(object): 
    def __init__(self, app=None): 
     self.app = app 
     if app is not None: 
      self.init_app(app) 

    def init_app(self, app): 
     app.extensions['my_extension'] = SomeResource() 

app = Flask(__name__) 
my_extension = MyExtension(app) 

Eğer her uygulama için (yukarıda) gibi kendi kaynağını vermek istiyorsanız seçebilir veya Bunun yerine her zaman geçerli uygulama

from flask import _request_ctx_stack 
try: 
    from flask import _app_ctx_stack 
except ImportError: 
    _app_ctx_stack = None 

stack = _app_ctx_stack or _request_ctx_stack 

class SomeResource(object): 
    def do_something(self): 
     ctx = stack.top 
     app = ctx.app 
my_resource = SomeResource() 
my_resource.do_something() 
işaret ettiği paylaşılan kaynağı kullanmak olsaydınız

Bunu uygulama bağlamında saklamak istediğinizi sanmıyorum çünkü "Flask nesnesinin ne zaman başlatılmaya başlayacağı ve ilk istek geldiğinde örtük olarak bittiği için"

Bunun yerine kaynağınızda modül seviyesi. Daha sonra uygulamayı bir uzantı olarak ekleyebilir ya da evet, konfigürasyonda bile, daha hızlı ve daha hızlı bir uzantı oluşturmak için daha tutarlı ve mantıklı olacaktır.

+0

IMO 'current_app.extensions ['my_extension']' en iyi yaklaşımdır. – zengr

+1

Bir veritabanı bağlantısını isteklere göre paylaşmak yaygın bir uygulamadır. Ama Flask web sitesindeki belgelerin çok yanıltıcı olduğunu düşünüyorum. Aslında burada açıklandığı gibi her istek için veritabanı bağlantıları kurulacaktır. http://flask.pocoo.org/docs/0.10/appcontext/ – hanson

0

Bu bir Python sorundur, Flask ve diğer web çerçevelerinin buna izin vermemesinin nedeni/bunu çok zorlaştırmak çünkü eşzamanlılık için tanımlanmış bir bellek modeli yoktur. Örneğin. Web sunucunuzun isteklerini kendi süreçlerinde (örneğin Gunicorn) sunacağını varsayalım. Bu işlem, ana sürecin kesilmesini ve böylece "global" değişkeninizi kopyalamanızı sağlayacaktır. Pencerelerde bir sunucu çalıştırıyorsanız, bir çatal eksikliğinden dolayı, tüm modülleri yeniden canlandıran yeni bir süreç yapacaktır, muhtemelen ana durumunuzda yapılan değişiklikleri hatırlamayan global durumunuzun temiz bir sürümünü üretecektir. -Thread. Ya da bir isim muhafızı ardında ilan ederseniz onu hiç bulamazsınız.

Sürekli olarak bunu "doğru" yapmanın iki yolu vardır. Biri, küresel durumunuzu korumak için tek bir iş parçacığıyla sınırlı olan bir webapp oluşturmak ve diğer webapp çağrılarınızı bu web sunucusundan almaktır.

İkincisi, Jython + iş parçacığı kullanmaktır. Jython bir JVM'de çalıştığı için, paylaşılan durumla iyi tanımlanmış bir bellek modeline sahip olduğundan, kapsayıcı yönetilen eşzamanlılık gibi tüm java EE hilelerini kullanabilirsiniz.