3

Я работаю над дизайном API на основе python. На данный момент я встречал проблему с двумя разными требованиями. С одной стороны я хотел бы предоставить надежный способ очистки ресурсов, связанных с API. Так как я знаю, что лучший способ сделать это состоит в использовании менеджеров контекста как:разработка python api. надежная очистка и простой в использовании в интерпретаторе

# lib 

class Client(object): 
    def __enter__(self): 
    return self 

    def __exit__(self, exc_type, exc_val, tb): 
    do_cleanup() 

    def method1(self): 
    pass 

    def method2(self): 
    pass 

# api user 
import mylib 

with mylib.Client() as client: 
    client.method1() 
    client.method2() 

С другой стороны, я хотел бы предоставить возможность беспрепятственно использовать мой LIB в интерактивном интерпретаторе. Но использование сложной конструкции, такой как with или try-except-finally, в интерпретаторе делает использование интерпретатора не столь привлекательным, потому что with -block рассматривается как один оператор. И это было бы предпочтительнее использовать один оператор за один метод апи как:

# interpreter session 

>>> import mylib 
>>> client = mylib.Client() 
<client object at ...> 
>>> client.method1() 
True 
>>> client.method2() 
100 

Итак, я мог иметь какие-либо варианты здесь? Определенно существует способ предоставить различную семантику использования для скриптов и интерпретатора, но я хотел бы использовать его в качестве последнего средства.

+3

Почему бы не сделать, как 'open' делает; вы можете либо использовать диспетчер контекста, либо явно «закрыть» (который вы можете легко реализовать в качестве вызова '__exit__'). – jonrsharpe

ответ

2

Типичный способ сделать это - предоставить метод для очистки вручную и использовать метод __exit__. Для вашего примера, если do_cleanup был реализован как метод, его можно просто вызывать из интерпретатора по завершении его работы.

class Client(object): 
    def __enter__(self): 
    return self 

    def __exit__(self, exc_type, exc_val, tb): 
    self.do_cleanup() 

    def do_cleanup(self): 
    pass 

    def method1(self): 
    pass 

    def method2(self): 
    pass 

Затем в интерпретаторе:

>>> import mylib 
>>> client = mylib.Client() 
<client object at ...> 
>>> client.method1() 
True 
>>> client.method2() 
100 
>>> client.do_cleanup() 

Я бы рекомендовал переименовать do_cleanup в close или подобное, так что сходство между File Objects более очевидна.

0

Вы можете создать свою логику «базовый», с open и close функций в модуле реализации, и распространить эти классы с контекстным менеджер:

#in private module mymodule.impl 
class Base(object): 
    def open(self, ...): 
     ... 
    def close(self): 
     ... 

Этот файл будет обычно не быть включен клиентом код.

Вместо импорта код клиента exported.api, который выглядит следующим образом:

#in public package mymodule 
import mymodule.impl 

class Base(mymodule.impl.Base): 
    def __enter__(self): 
     return self 
    def __exit__(self, ...): 
     self.close()