You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python多进程与pyftpdlib运行多FTP实例失败求助

问题描述

尝试在本地主机(127.0.0.1)上运行两个FTP服务器实例,分别监听1024和1025端口,但实际仅一个实例正常运行。

原代码

create_multiple_ftp_servers.py

# "create_multiple_ftp_servers.py"

from multiprocessing import Pool

import sys
sys.path.insert(1, r'C:\Users\Desktop\PythonCodes')

import create_ftp_server

ftp_server_dict = {'ftp1': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1024],
                   'ftp2': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1025]}

for k, v in ftp_server_dict.items():
    with Pool(5) as p:
        server_instance = p.map(create_ftp_server.ftp, [v,])
        p.close()

create_ftp_server.py

import os

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer


def ftp(data):
    # Instantiate a dummy authorizer for managing 'virtual' users
    authorizer = DummyAuthorizer()

    # Define a new user having full r/w permissions and a read-only
    # anonymous user
    authorizer.add_user(data[1], data[2], data[3], perm='elradfmwMT')
    authorizer.add_anonymous(os.getcwd())

    # Instantiate FTP handler class
    handler = FTPHandler
    handler.authorizer = authorizer

    # Define a customized banner (string returned when client connects)
    handler.banner = "pyftpdlib based ftpd ready."

    # Specify a masquerade address and the range of ports to use for
    # passive connections.  Decomment in case you're behind a NAT.
    # handler.masquerade_address = '151.25.42.11'
    handler.passive_ports = range(60000, 65535)

    # Instantiate FTP server class and listen on 0.0.0.0:2121
    address = (data[0], data[4])
    server = FTPServer(address, handler)

    # set a limit for connections
    server.max_cons = 256
    server.max_cons_per_ip = 5

    # start ftp server
    server.serve_forever()
问题根源
  1. 阻塞调用中断循环:p.map()是阻塞方法,第一个FTP服务器调用serve_forever()进入无限循环后,map()会一直等待该任务完成,主进程无法进入循环的下一次迭代,第二个服务器永远不会被启动。
  2. 进程池重复创建无效:每次循环创建新的Pool,且with语句会在代码块结束时自动关闭进程池,但由于map()的阻塞特性,第一个with块根本不会结束,后续逻辑无法执行。
解决方案

以下两种方式均可解决问题:

方式一:使用进程池异步提交任务

# "create_multiple_ftp_servers.py"
from multiprocessing import Pool
import sys
sys.path.insert(1, r'C:\Users\Desktop\PythonCodes')
import create_ftp_server

ftp_server_dict = {'ftp1': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1024],
                   'ftp2': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1025]}

# 创建单个进程池,异步提交所有服务器任务
with Pool(2) as p:
    for config in ftp_server_dict.values():
        p.apply_async(create_ftp_server.ftp, args=(config,))
    # 等待所有子进程持续运行(无限阻塞,直到手动终止)
    p.close()
    p.join()

方式二:直接创建独立进程(更直观)

# "create_multiple_ftp_servers.py"
from multiprocessing import Process
import sys
sys.path.insert(1, r'C:\Users\Desktop\PythonCodes')
import create_ftp_server

ftp_server_dict = {'ftp1': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1024],
                   'ftp2': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1025]}

process_list = []
# 为每个服务器配置创建独立进程
for config in ftp_server_dict.values():
    server_process = Process(target=create_ftp_server.ftp, args=(config,))
    process_list.append(server_process)
    server_process.start()

# 等待所有进程持续运行
for proc in process_list:
    proc.join()

说明

  • 两种方式都避免了阻塞调用导致的循环中断,确保两个FTP服务器都能启动并持续运行。
  • create_ftp_server.py无需修改,每个子进程会独立初始化自身的FTP服务配置,端口不会冲突。

内容的提问来源于stack exchange,提问作者RRSC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 04:35:28