是否有必要在Paramiko中使用多线程打开每个线程的SFTPClient?

时间:2018-05-19 03:34:26

标签: python multithreading ssh sftp paramiko

我想使用多线程的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. 通过单一连接下载多个文件是否有效?
  3. 所以这是我的第二个解决方案:

    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)
    

    哪种解决方案更好?

1 个答案:

答案 0 :(得分:2)

Paramiko不是线程安全的。

在一个连接上使用多个线程无论如何都不会给您带来任何性能优势。

您必须为每个线程打开一个单独的连接。