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

Python multiprocessing报NameError: name 'server'未定义

错误产生原因
  • Python multiprocessing在Windows、macOS系统下默认使用spawn模式创建子进程:子进程启动时会重新从头导入主脚本,不会执行if __name__ == "__main__"判断块内的代码,你在这个块里定义的server变量根本不会在子进程中被创建,add_users函数运行时自然找不到server,抛出NameError。
  • 你代码里声明的global users、global client等全局变量也存在同样问题:就算解决了server的定义问题,子进程里这些变量也没有被初始化,会继续抛同类错误。
  • 代码里还有两处基础逻辑错误:一是server.listen(100)不需要放在while True循环里重复调用,整个服务生命周期只需要执行一次;二是for t in len(users)写法不合法,len()返回整数,不能直接用于迭代。
  • 多进程之间内存完全隔离,就算你在各子进程里分别定义了同名的users变量,也是各自独立的副本,一个进程新增的连接用户不会同步到另一个进程,直接用全局变量没法实现数据共享。
修复方案

核心原则:子进程依赖的资源要么在子进程内部初始化,要么通过函数参数显式传入;跨进程共享数据必须用multiprocessing提供的进程安全组件,不能用普通全局变量。

  • 把socket初始化、监听逻辑移到add_users所属的子进程内部执行,不需要在主进程提前创建server对象。
  • 用multiprocessing.Queue作为进程间通信的通道,add_users进程接到新客户端连接后,把连接信息放到队列里,mid进程从队列读取连接信息维护用户列表。
  • 修正原有语法错误,把递归实现的输入循环改成while True写法避免栈溢出。

修正后的可运行核心代码如下:

import socket
import os
import time
import multiprocessing
import colorama
from colorama import colored

def add_users(users_queue, host, port):
    # 子进程内部初始化服务端socket
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind((host, port))
    server.listen(100)  # listen仅需调用一次
    print(colored('[+] Listening For Client Connection ...', 'magenta'))
    while True:
        client, client_addr = server.accept()
        print(colored(f'[+] {client_addr} Client connected to the server', 'yellow'))
        users_queue.put([client, client_addr])  # 新连接写入进程安全队列

def exec_cmd(c, cA):
    # 原有命令执行逻辑
    pass

def mid(users_queue):
    users = []
    while True:
        # 先从队列拉取所有新连接,更新本地用户列表
        while not users_queue.empty():
            users.append(users_queue.get())
        
        a = input(colored("#-> ", 'green'))
        if a == 'ls':
            if len(users) != 0:
                print(colored(users, 'yellow'))
            else:
                print(colored("No user connected.", 'yellow'))
        elif a.split(' ')[0] == 'connect':
            if len(a.split(' ')) < 2:
                print(colored("Please input target address", 'yellow'))
                continue
            target_addr = a.split(' ')[1]
            for user in users:
                if str(user[1]) == target_addr:
                    exec_cmd(user[0], user[1])
                    break
            else:
                print(colored("Target user not connected", 'yellow'))

if __name__ == "__main__":
    colorama.init()
    os.system('color')

    # 打印启动banner
    print(colored(' ______     __  __        __    __     ______     __  __     ______     _____    ', 'red'))
    time.sleep(1)
    print(colored('/\  == \   /\ \_\ \      /\ "-./  \   /\  __ \   /\ \/\ \   /\  __ \   /\  __-.  ', 'red'))
    time.sleep(1)
    print(colored('\ \  __<   \ \____ \     \ \ \-./\ \  \ \ \/\ \  \ \ \_\ \  \ \  __ \  \ \ \/\ \ ', 'red'))
    time.sleep(1)
    print(colored(' \ \_____\  \/\_____\     \ \_\ \ \_\  \ \_____\  \ \_____\  \ \_\ \_\  \ \____- ', 'red'))
    time.sleep(1)
    print(colored('  \/_____/   \/_____/      \/_/  \/_/   \/_____/   \/_____/   \/_/\/_/   \/____/ \n', 'red'))

    HOST = '0.0.0.0'
    PORT = 8081
    print(colored('[+] Server Started', 'magenta'))

    # 初始化进程安全队列,用于跨进程传递用户连接信息
    users_queue = multiprocessing.Queue()

    # 启动两个子进程,通过args传入需要的参数
    p1 = multiprocessing.Process(target=mid, args=(users_queue,))
    p2 = multiprocessing.Process(target=add_users, args=(users_queue, HOST, PORT))

    p1.start()
    p2.start()

    # 等待子进程结束
    p1.join()
    p2.join()

补充说明:不要在if __name__ == "__main__"块内使用global声明变量,该块本身处于模块顶层作用域,直接赋值就会生成模块级全局变量,但spawn模式下子进程不会执行该块代码,因此这里定义的变量无法被子进程读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 21:36:20