今天,在编程时,我发现自己在生成器函数内管理资源(ssh 连接),类似于以下内容:
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
的生成器,以便连接始终关闭。我是否应该担心有人(例如未来的我)使用生成器而没有完全消耗它并保持连接打开?有办法防止吗?
(作为旁注,这里我决定使用生成器函数,因为我想避免循环遍历文件名列表两次或多次)。
以这种方式管理生成器函数内的资源是不好的做法吗?
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)