支持"开放"不使用contextlib.closing()的语法

时间:2014-03-14 06:02:35

标签: python

我非常喜欢语法" open(' in_file'')为f"。 我想将这种语法用于我自己的资源,必须打开和关闭。

但是,我不明白如何更改我的open()方法以启用''句法。 我可以(并且确实)使用contextlib.closing()方法,但重复使用后会变得有点笨重。

因此,我将在下面提出有关shelve.open()的问题。 我不是建议更改搁置模块,而是使用它,因为源代码随时可供所有人使用。

shelve.open()与其他需要关闭的标准库资源没有什么特别之处:socket.socket(),sqlite3.connect(),urllib2.urlopen()等。

import contextlib, inspect, shelve, sys

#print(inspect.getsource(open))  # can not see how it was done here :-(

print('-' * 40)
# Given that we can view the source for the shelve module:
print(inspect.getsource(shelve))

print('-' * 40)
# Given that we can view the docs for the shelve module:
print(shelve.__doc__)

#print('-' * 40)
# Given that the desired syntax is Pythonic but is not supported:
#with shelve.open('test_shelve') as my_shelve:
#    my_shelve['fact_number_1'] = "There's a dead fish on the landing."

# Given that the required syntax is convoluted and
#    takes programmer attention away from the task at hand:
with contextlib.closing(shelve.open('test_shelve')) as my_shelve:
    my_shelve['fact_number_2'] = "There's another dead fish on the landing."

# Q: What changes would need to made to shelve.open() to allow the
#    'with shelve.open(x) as y' syntax?

我对一个名字不同的额外包装并不感兴趣。使用contextlib.closing()比这更容易,更安全,更直观。我真正感兴趣的是创建一个open()方法,可以使用或不使用'来调用。

因此,要成功回答这个问题,您需要获取搁置模块的源代码,并显示需要对shelve.open()进行哪些更改以使单个方法可以使用或不使用'与' (比如内置的open()或Python3的urllib.urlopen())。

1 个答案:

答案 0 :(得分:2)

这里最大的问题是如果你做了

shelf = the_function_you_want()

您想要的功能必须返回架子,但如果您这样做

with the_function_you_want() as shelf:

您想要的功能必须返回上下文管理器。这意味着您需要返回一个也是上下文管理器的架子,这反过来意味着您需要创建一个架子类或猴子补丁Shelf。制作子类可能更好:

class ContextManagerShelf(shelve.DbfilenameShelf):
    def __enter__(self):
        return self
    def __exit__(self, *exc_info):
        self.close()

然后您可以使用ContextManagerShelf作为上下文管理器。签名与shelve.open相同。如果需要,您还可以使用open功能。