【问题标题】:Python - FTP Connection PoolPython - FTP 连接池
【发布时间】:2020-06-17 08:46:47
【问题描述】:

我有一个通用的多进程脚本,可以在多进程设置中运行任何任务。我将任务作为命令行参数注入,并使用 getattr 调用注入代码中的函数。

taskModule = importlib.import_module(taskFile.replace(".py", ""))
taskContext = getattr(taskModule, 'init')()
response = pool.map_async(getattr(taskModule, 'run'), inputList)

init() 函数为要执行的任务创建所有相关变量,并将它们作为 dict 对象(taskContext)返回。 inputList 是 dict 对象的列表,每个 dict 都包含 taskContext 对象以及要处理的特定项,因此每个进程都会获得一个要处理的唯一项以及任务所需的上下文副本。

其中一项任务适用于 FTP,在这种情况下,taskContext 包含有关 FTP 服务器的信息以及其他详细信息。 FTP 任务中的 run 函数几乎可以使用上下文变量打开连接,上传所需的文件并关闭它,这非常有效。

但是,我认为如果我可以在开始时设置一个具有多个 FTP 连接的连接池,作为创建上下文时 init() 函数的一部分,然后在 as- run 方法中的可用方式,非常类似于 DB 连接池,可防止每次都打开和关闭与数据库的连接。

这甚至可行吗?如果是这样,最好的方法是什么?

【问题讨论】:

    标签: python ftp


    【解决方案1】:

    我组装了一个connection_pool 模块作为概念验证的一部分。我不确定它有多强大。

    我添加了关闭到this 的连接,这是this 的错误修复。

    我能够设置 FTP 和 SFTP 连接的连接池,通过 10-20 个线程传输数千个文件。

    你可以从 conda 安装我的版本:

    conda install -c jmeppley connectionpool
    

    创建 FTP 池如下所示:

    # this is from snakemake
    def connect(*args_to_use, **kwargs_to_use):
            ftp_base_class = (
                ftplib.FTP_TLS if kwargs_to_use["encrypt_data_channel"] else ftplib.FTP
            )
    
            ftp_session_factory = ftputil.session.session_factory(
                base_class=ftp_base_class,
                port=kwargs_to_use["port"],
                encrypt_data_channel=kwargs_to_use["encrypt_data_channel"],
                debug_level=None,
            )
    
            return ftputil.FTPHost(
                kwargs_to_use["host"],
                kwargs_to_use["username"],
                kwargs_to_use["password"],
                session_factory=ftp_session_factory,
            )
    
    # a function to create a pool using the connect() method
    def create_ftp_pool(pool_size, *args_to_use, **kwargs_to_use):
        create_callback = partial(connect, *args_to_use, **kwargs_to_use)
        connection_pool = ConnectionPool(create_callback, 
                                         close=lambda c: c.close(), 
                                         max_size=pool_size)
    
    
    # create a pool with the arguments you'd use to create a connection
    pool_size = 10
    ftp_pool = create_ftp_pool(pool_size, host=...)
    
    # use item() as a context manager
    with ftp_pool.item() as connection:
        ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      • 2018-09-03
      • 2020-11-01
      • 1970-01-01
      • 2023-02-01
      • 2013-08-20
      • 1970-01-01
      相关资源
      最近更新 更多