在Python中展平“with”和“try/finally”

2024-05-29 11:04:45 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑以下代码:

async with app:
    ...
    async with app.resource as rsrc:
        ...
        async with rsrc.foo as bar:
            ...

大量嵌套的withasync with语句对代码的可读性有负面影响,特别是在测试中,同一子句可能会被多次重用。你知道吗

在像D这样的语言中,有一个scope(exit) ...构造,它允许您将代码附加到范围终结器列表中—这个代码将在范围离开后执行,允许您有效地执行__exit__所做的操作,但不添加缩进。你知道吗

有没有办法在Python中展平with并执行类似的操作?你知道吗

await async_with(app)
scope_exit(app.quit)

...

rsrc = await async_with(app.resource)
scope_exit(rsrc.release)

...

bar = await async_with(rsrc.foo)
scope_exit(lambda: bar.unfrob())

...

或者,是否有一种方法可以在退出作用域时可靠地执行任意代码?你知道吗


Tags: 代码appasyncfooaswithexitbar
2条回答

据我所知,你不能达到你想要的。尤其是因为不可能定义这样的“范围”。你知道吗

即使在伪代码中:

await async_with(app)
scope_exit(app.quit)

...

rsrc = await async_with(app.resource)
scope_exit(rsrc.release)

...

bar = await async_with(rsrc.foo)
scope_exit(lambda: bar.unfrob())

raise ExceptionHere()

什么样的背景应该[不]抓住它?你知道吗

我可能错了,但是设置捕获异常的“保护”的唯一方法是try/except子句。with大致是它的一个包装器。你知道吗

说到动机,如果你对嵌套的上下文管理器有太大的问题,你可能应该重构你的核心,将内部上下文提取为函数。您可以查看contextlib以获得帮助

我受不了with语句中的额外缩进。。。我就是这么做的:

嵌套:

def stuff_with_files(path_a, path_b):
    # ... do stuff
    with open(path_a) as fileA:
        # ... do stuff with fileA
        with open(path_b) as fileB:
            # ... do stuff with fileA and fileB

def main():
    stuff_with_files('fileA.txt', 'fileB.txt')

扁平化:

# Extract the 'with' statement.
def with_file(path, func, *args, **kwargs):
    with open(path) as file:
        func(file, *args, **kwargs)


def process_a_b(fileB, results_of_a):
    # ... do stuff with fileB and results_of_a.


def process_a(fileA):
    # ... do stuff with fileA
    results = # ...
    with_file('fileB.txt', process_a_b, results)


def main():
    with_file('fileA.txt', process_a)

相关问题 更多 >

    热门问题