2012-07-11 11 views
11

ifadesiyle birlikte kullanıyor. Diğer içerik yöneticilerini kullanan bir içerik yöneticisi yazmaya çalışıyorum, böylece istemcilerin tüm tarifleri bilmemeleri yeterli. @contextmanager kullanarak yapılamıyorum - yield numaralı çağrıdan sonra gelen kod, bir istisna ile kesintiye uğradığınızda çalıştırılamıyor, bu yüzden sınıf tabanlı bir yönetici kullanmam gerekiyor. Bir sınıf anlatmak için herhangi bir yolu var mıPython'da bir içerik yöneticisi yazarak, kendisi bir

before 
{} 

enter one 
enter two 
enter complex three 
{'one': 1, 'three': 3, 'two': 2} 

exit complex three 
exit two 
exit one 
after 
{} 

: Ben çıkış Buna istiyorum

before 
{} 

enter one 
enter two 
enter complex three 
exit two 
exit one 
{'three': 3} 

exit complex three 
after 
{} 

:

from contextlib import contextmanager 
import pprint 

d = {} 

@contextmanager 
def simple(arg, val): 
    print "enter", arg 
    d[arg] = val 
    yield 
    print "exit", arg 
    del d[arg] 

class compl(object): 
    def __init__(self, arg, val): 
     self.arg=arg 
     self.val=val 

    def __enter__(self): 
     with simple("one",1): 
      with simple("two",2): 
       print "enter complex", self.arg 
       d[self.arg] = self.val 

    def __exit__(self,*args): 
     print "exit complex", self.arg 
     del d[self.arg] 

print "before" 
print d 
print "" 

with compl("three",3): 
    print d 
    print "" 

print "after" 
print d 
print "" 

bu çıkışı: Burada

biraz betik örneği tabanlı içerik yöneticisi kendini diğer içerik yöneticileri ile sarmak için mi?

+2

Python sürümünü belirlemek yararlı olurdu. –

+0

Özür dilerim, ama neden bunu yapmak istersiniz? Sınıf-temelli içerik yöneticisinin, bağımlılıklarını temizledikten sonra son çıkması sadece bana doğal geliyor. –

+0

Hedefleme python 2.7, üzgünüm –

cevap

12
@contextmanager 
def compl(arg, val): 
   with simple("one",1): 
        with simple("two",2): 
      print "enter complex", arg 
      try: 
                d[arg] = val 
       yield 
      finally: 
          del d[arg] 
          print "exit complex", arg 
+3

Sorunun ne olduğunu anlayabilmeniz için daha fazla soru sorabilecek misiniz? :) – n611x007

+1

@naxa: sorudaki son iki çıktı örneğine bakın. Sorudaki kod ilk çıktıyı üretiyor, cevabımdaki kodum ikinci olanı üretiyor (arzu edilen). Özetle: en iç içe içerik yöneticisi en erken çıkmalıdır. – jfs

1

ne yaptığınızı ile sorun, kendi sarma bağlam yöneticisi girdiğinizde sizin __enter__ çağrısında with kullanarak, her iki girin ve ardından sarılmış bağlam yöneticileri bırakarak olmasıdır. Sarmalayıcıya girdiğinizde sarılmış içerik yöneticilerine giren kendi içerik yöneticinizi yazmak istiyorsanız, ayrıldığınızda bunları çıkar, sarılmış içerik yöneticilerinin işlevlerini el ile çağırmanız gerekir. Muhtemelen istisna güvenliği konusunda da endişelenmeniz gerekiyor.

2

"@contextmanager kullanarak yapamıyorum - bir istisna ile kesintiye uğrarsanız verim çağrısı gerçekleştirilmediğinde kod yazamazsınız." Çalıştırılması gereken bir kodunuz varsa, onu bir try/finally bloğuna koyabilirsiniz.

import contextlib 

@contextlib.contextmanager 
def internal_cm(): 
    try: 
     print "Entering internal_cm" 
     yield None 
     print "Exiting cleanly from internal_cm" 
    finally: 
     print "Finally internal_cm" 

@contextlib.contextmanager 
def external_cm(): 
    with internal_cm() as c: 
     try: 
      print "In external_cm_f" 
      yield [c] 
      print "Exiting cleanly from external_cm_f" 
     finally: 
      print "Finally external_cm_f" 

if "__main__" == __name__: 
    with external_cm() as foo1: 
     print "Location A" 
    print 
    with external_cm() as foo2: 
     print "Location B" 
     raise Exception("Some exception occurs!!") 

Çıktı:

Entering internal_cm 
In external_cm_f 
Location A 
Exiting cleanly from external_cm_f 
Finally external_cm_f 
Exiting cleanly from internal_cm 
Finally internal_cm 

Entering internal_cm 
In external_cm_f 
Location B 
Finally external_cm_f 
Finally internal_cm 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Anaconda\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 540, in runfile 
    execfile(filename, namespace) 
    File "C:\untitled0.py", line 35, in <module> 
    raise Exception("Some exception occurs!!") 
Exception: Some exception occurs!! 
İlgili konular