【问题标题】:Is it necessary to open a SFTPClient per one thread in Paramiko with multi-threading?是否有必要在多线程的 Paramiko 中为每个线程打开一个 SFTPClient?
【发布时间】:2018-10-29 11:54:59
【问题描述】:

我想使用多线程的 Paramiko 从远程服务器下载文件。

我想到了两个解决方案,但我不确定哪个是正确的(或更好)。

解决方案 1: 假设SFTPClient.get 是线程安全的(但我找不到任何提到的文档),一个简单的方法是:

from paramiko import SSHClient, AutoAddPolicy, SFTPClient
from concurrent.futures import ThreadPoolExecutor
from typing import List

client = SSHClient()
ciient.set_missing_host_key_policy(AutoAddPolicy())
client.connect( ... )
sftp = client.open_sftp()

files_to_download: List[str] = ...

with ThreadPoolExecutor(10) as pool:
    pool.map(lambda fn: sftp.get(fn, fn), files_to_download)

解决方案 2:解决方案 1

中有两个问题
  1. Paramiko 的 API 真的是线程安全的吗?
  2. 通过单个连接下载多个文件是否有效?

所以这是我的第二个解决方案:

from paramiko import SSHClient, AutoAddPolicy, SFTPClient
from concurrent.futures import ThreadPoolExecutor
from threading import Lock, local
from typing import List

client = SSHClient()
ciient.set_missing_host_key_policy(AutoAddPolicy())
client.connect( ... )
thread_local = local()
thread_lock  = Lock()

files_to_download: List[str] = ...

def download(fn: str) -> None:
    """
    thread-safe and each thread has its own SFTPClient
    """
    if not hasattr(thread_local, 'sftp'):
        with thread_lock:
            thread_local.sftp = client.open_sftp()
    thread_local.sftp.get(fn, fn)

with ThreadPoolExecutor(10) as pool:
    pool.map(download, files_to_download)

哪种解决方案更好?

【问题讨论】:

    标签: python multithreading ssh sftp paramiko


    【解决方案1】:

    Paramiko 不是线程安全的。

    在一个连接上使用多个线程可能无法获得您希望的性能。您必须为每个线程打开一个单独的连接 (SSHClient/SFTPClient)。

    只有在传输大量小文件这样的场景下,只有一个连接,您才能获得更好的性能。为此,请参阅Slow upload of many small files with SFTP

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      • 2021-05-09
      • 2012-04-18
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多