【问题标题】:Does paramiko close ssh connection on a non-paramiko exceptionparamiko 是否在非 paramiko 异常时关闭 ssh 连接
【发布时间】:2023-08-26 15:52:01
【问题描述】:

我正在调试一些代码,这将导致我不断地登录/退出一些外部 sftp 服务器。如果代码中引发非 paramiko 异常,有谁知道 paramiko 是否会自动关闭外部服务器上的 ssh / sftp 会话?我在文档中找不到它,并且由于必须在每次迭代中相当早地建立连接,我不希望最终有 20 个打开的连接。

【问题讨论】:

    标签: python ssh paramiko


    【解决方案1】:

    SSHClient() 可以用作上下文管理器,所以你可以这样做

    with SSHClient() as ssh:
       ssh.connect(...)
       ssh.exec_command(...)
    

    不要手动关闭。

    【讨论】:

    • 这比try: ... finally: ...好多了!
    • 如果在这个执行过程中抛出一些异常怎么办?
    • @runnerpaul 上下文管理器旨在处理这个问题。无论你如何离开该块,无论是正常执行,return,执行,任何事情,连接都会关闭。
    • 这应该是公认的答案。 with 语句早在 PEP 343 中就被引入,以便排除 try/finally 语句。
    【解决方案2】:

    不,paramiko 不会自动关闭 ssh / sftp 会话。异常是由 paramiko 代码还是其他方式生成的都没有关系; paramiko 代码中没有任何内容可以捕获任何异常并自动关闭它们,因此您必须自己做。

    您可以通过将其包装在 try/finally 块中来确保它被关闭,如下所示:

    client = None
    try:
        client = SSHClient()
        client.load_system_host_keys()
        client.connect('ssh.example.com')
        stdin, stdout, stderr = client.exec_command('ls -l')
    finally:
        if client:
            client.close()
    

    【讨论】:

    • 谢谢,问题是我正在调试几千行代码(并且仍在添加)。 paramiko 没有提出异常,而是在其他地方出现问题时由subprocessos 等提出。我想我可以在每个异常中添加client.close(),但这不是很漂亮。
    • 如果你把对subprocessos 的调用放在try 块内,那么finally 块将始终被调用,无论是什么产生了异常。如果您希望它更漂亮一点,那么您可能希望将客户端包装在 Context Manager 中并使用 with 语句。 docs.python.org/reference/datamodel.html#context-managers
    • 那位先生是一个点,所以+1!不回答这个问题,如果所有 finally 都是相同的,那么将每个单独的东西放在 try ... finally 块中没有什么意义。但是,将类的调用放在一个里面并没有错,所以我总是干净利落地关闭它。
    • 如何发布代码(或其简化版本),然后更容易准确地说出您需要做什么才能不打开 20 个连接。
    • 我编辑了我的答案以更具体地解决您的问题...不,无论在哪里生成异常,paramiko 都不会自动关闭连接。