确保生成器函数内的连接被调用者关闭[关闭]

问题描述 投票:0回答:1

今天,在编程时,我发现自己在生成器函数内管理资源(ssh 连接),类似于以下内容:

#I decided to use a generator to avoid looping through the list of fnames 2 times

def _yield_fname(host_address, usr, pwd, datapath):
    with paramiko.SSHClient() as ssh_client:

        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh_client.connect(host, username=usr, password=pwd)
        
        stdin, stdout, stderr = ssh_client.exec_command(
            'find . -type d -maxdepth 1 -printf "%f\n"'
        )
        for line in stdout:
            yield fname

def get_foos():

    foos= []
    for fname in self._yield_fname(self.FOO_PATH):
        foos.append(Foo.from_fname(fname))
    
    return foos

def get_bars():

    bars= []
    for fname in self._yield_fname(self.FOO_PATH):
        bars.append(Bar.from_fname(fname))
    
    return bars

就我而言,我计划从头到尾始终消耗

yield_fname
的生成器,以便连接始终关闭。

但是,我担心有人(例如,未来的我)可能会使用生成器而没有完全消耗它,从而使连接保持打开状态。

有没有办法表明发电机在使用后应该关闭,即使没有完全消耗?

python yield with-statement
1个回答
3
投票

以这种方式管理生成器函数内的资源是不好的做法吗?

IMO 不,这是很正常的用法

我是否应该担心有人(例如未来的我)使用生成器而没有完全消耗它并保持连接打开?

可能不是,但这可能是一个问题。我相当确定(如所写),只要生成器尚未耗尽或垃圾收集,上下文管理器就会“存活”。

不过,我通常不会担心这一点,在大多数 Python 用例的上下文中,这是一种性能/资源边缘情况,其中严格的性能和资源管理并不是高优先级。

有办法防止这种情况吗?

您可以在生成器外部创建上下文,并将其传入。即使生成器没有耗尽,您仍然可以退出上下文。

gen = None  # even if we keep generator from being garbage collected
found = None
with get_resource() as res:
    gen = build_generator(res)
    for item in gen:
        if desired(item):
            found = item
            break  # incomplete iteration

print(item)
© www.soinside.com 2019 - 2024. All rights reserved.