3

我正在设计基于 python 的 API。目前,我遇到了两个不同要求的问题。一方面,我想提供一种可靠的方式来清理 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()

另一方面,我想提供一种在交互式解释器中无缝使用我的库的方法。with但是在解释器中使用类似or的复合结构try-except-finally使得解释器的使用不那么时髦,因为with-block 被视为单个语句。并且最好对每个单个 api 方法使用单个语句,例如:

# interpreter session

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

那么,我可以在这里有任何选择吗?绝对有一种方法可以为脚本和解释器提供不同的使用语义,但我想把它作为最后的手段。

4

2 回答 2

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_cleanupclose或类似,以便文件对象之间的相似性更加明显。

于 2014-12-17T13:22:57.540 回答
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()
于 2014-12-17T13:24:05.457 回答