使用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()
问题根源
- 阻塞调用中断循环:
p.map()是阻塞方法,第一个FTP服务器调用serve_forever()进入无限循环后,map()会一直等待该任务完成,主进程无法进入循环的下一次迭代,第二个服务器永远不会被启动。 - 进程池重复创建无效:每次循环创建新的
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
相关产品推荐
相关产品推荐

