2013-03-12 30 views
6

Veritabanından bir istek/yanıt döngüsü sırasında değişmeyecek bir değer için bir bellek içi iş parçacığı önbelleği kullanmak istiyorum, ancak yüzlerce (potansiyel olarak binlerce) kez çağrılır. Benim sınırlı anlayışım, bir "global"/module değişkeni kullanmak, bu tip bir önbellek uygulamak için bir yoldur.Python "global" (modül) değişkenleri yerel olarak mı işlenir?

örn:

#somefile.py 

foo = None 

def get_foo(request): 
    global foo 
    if not foo: 
    foo = get_foo_from_db(request.blah) 
    return foo 

ben "küresel" bu tür kullanarak Python evreli olup olmadığını merak ediyorum ve bu nedenle ben get_foo_from_db() istek başına sadece bir kere çağrılan alacak o rahat olabilir django'da/yanıt döngüsü (runserver veya gunicorn + gevent kullanarak). Anlayışım doğru mu? Bu şey, değeri depolamak için memcached'i kullanmanın bile bir darboğaz olacağına (konuştuğumuz şekilde profil oluşturduğuma) yetinir.

cevap

3

Hayır, iki sayımda yanılıyorsunuz.

İlk olarak, "iş parçacığı" kullanımı burada biraz belirsizdir. Sunucunun nasıl yapılandırıldığına bağlı olarak, Django, iş parçacığı veya işlemleri veya her ikisini de kullanarak sunulabilir (tam bir tartışma için bkz. mod_wsgi documentation). Her işlem için tek bir iş parçacığı varsa, her işlem için yalnızca bir modül örneğinin kullanılabileceğini garanti edebilirsiniz. Ancak bu, bu konfigürasyona fazlasıyla bağımlıdır. Yine de, istek/yanıt döngüsü başına bu işleve "tam olarak bir" çağrı olacak olması hala mümkün değildir. Bunun nedeni, bir sürecin kullanım ömrünün bu döngü için tamamen ilgisiz olmasıdır. Birden çok istek için bir süreç sürecektir, böylece değişken bu isteklerin tümü için geçerli olacaktır.

+0

Anlam ifade eder. Http://stackoverflow.com/questions/15365780/how-to-implement-thread-safe-in-memory-cache-of-value-in-django adresine buradan ulaşabilirsiniz. –

3

Hayır, globals erişimi thread-safe değildir. Dişler kendi global kopyasını almazlar, globals dişler arasında paylaşılır.

kodu:

if not foo: 
    foo = get_foo_from_db(request.blah) 

birkaç piton baytkodu ifadelerine derler: Eğer test sonrasında

2   0 LOAD_FAST    1 (foo) 
       3 POP_JUMP_IF_TRUE  24 

    3   6 LOAD_GLOBAL    0 (get_foo_from_db) 
       9 LOAD_FAST    0 (request) 
      12 LOAD_ATTR    1 (blah) 
      15 CALL_FUNCTION   1 
      18 STORE_FAST    1 (foo) 
      21 JUMP_FORWARD    0 (to 24) 

bir iplik geçiş, bu nedenle başka bir iş parçacığı foodeğiştirebilir her baytkodu yürütülmesinden sonra ortaya çıkabilir.

İlgili konular