一个Python脚本的多个控制台窗口

一个Python脚本的多个控制台窗口,python,windows,windows-console,Python,Windows,Windows Console,我见过类似的问题,比如这个: 然而,我有一个不同的情况。我不想在不同的控制台窗口中运行不同的脚本。我的想法是让套接字作为服务器运行并接受所有连接。当一个连接被接受时,一个新的控制台窗口被创建,所有输入和输出数据都显示在那里。这可能吗?一个进程一次只能连接到一个控制台(即conhost.exe实例),没有连接进程的控制台将自动关闭。您需要使用creationflags=CREATE\u NEW\u CONSOLE生成一个子进程 以下演示脚本需要Windows Python 3.3+。它生成两个工作

我见过类似的问题,比如这个:


然而,我有一个不同的情况。我不想在不同的控制台窗口中运行不同的脚本。我的想法是让套接字作为服务器运行并接受所有连接。当一个连接被接受时,一个新的控制台窗口被创建,所有输入和输出数据都显示在那里。这可能吗?

一个进程一次只能连接到一个控制台(即conhost.exe实例),没有连接进程的控制台将自动关闭。您需要使用
creationflags=CREATE\u NEW\u CONSOLE
生成一个子进程

以下演示脚本需要Windows Python 3.3+。它生成两个工作进程,并通过
socket.share
socket.fromshare
将每个套接字连接复制到工作进程中。封送的套接字信息通过管道发送到孩子的
stdin
。加载插座连接后,管道关闭,
CONIN$
作为
sys.stdin
打开,以从控制台读取标准输入

import sys
import time
import socket
import atexit
import threading
import subprocess

HOST = 'localhost'
PORT = 12345

def worker():
    conn = socket.fromshare(sys.stdin.buffer.read())
    sys.stdin = open('CONIN$', buffering=1)
    while True:
        msg = conn.recv(1024).decode('utf-8')
        if not msg:
            break
        print(msg)
        conn.sendall(b'ok')
    input('press enter to quit')
    return 0

def client(messages):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((HOST, PORT))
        for msg in messages:
            s.sendall(msg.encode('utf-8'))
            response = s.recv(1024)
            if response != b'ok':
                break
            time.sleep(1)

procs = []

def server():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen(1)
        while True:
            conn, addr = s.accept()
            with conn:
                p = subprocess.Popen(
                    ['python', sys.argv[0], '-worker'],
                    stdin=subprocess.PIPE, bufsize=0,
                    creationflags=subprocess.CREATE_NEW_CONSOLE)
                p.stdin.write(conn.share(p.pid))
                p.stdin.close()
                procs.append(p)

def cleanup():
    for p in procs:
        if p.poll() is None:
            p.terminate()

if __name__ == '__main__':
    if '-worker' in sys.argv[1:]:
        sys.exit(worker())

    atexit.register(cleanup)

    threading.Thread(target=server, daemon=True).start()

    tcli = []
    for msgs in (['spam', 'eggs'], ['foo', 'bar']):
        t = threading.Thread(target=client, args=(msgs,))
        t.start()
        tcli.append(t)

    for t in tcli:
        t.join()

    input('press enter to quit')

一个进程一次只能附加到一个控制台(即conhost.exe实例),没有附加进程的控制台将自动关闭。您需要使用
creationflags=CREATE\u NEW\u CONSOLE
生成一个子进程

以下演示脚本需要Windows Python 3.3+。它生成两个工作进程,并通过
socket.share
socket.fromshare
将每个套接字连接复制到工作进程中。封送的套接字信息通过管道发送到孩子的
stdin
。加载插座连接后,管道关闭,
CONIN$
作为
sys.stdin
打开,以从控制台读取标准输入

import sys
import time
import socket
import atexit
import threading
import subprocess

HOST = 'localhost'
PORT = 12345

def worker():
    conn = socket.fromshare(sys.stdin.buffer.read())
    sys.stdin = open('CONIN$', buffering=1)
    while True:
        msg = conn.recv(1024).decode('utf-8')
        if not msg:
            break
        print(msg)
        conn.sendall(b'ok')
    input('press enter to quit')
    return 0

def client(messages):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((HOST, PORT))
        for msg in messages:
            s.sendall(msg.encode('utf-8'))
            response = s.recv(1024)
            if response != b'ok':
                break
            time.sleep(1)

procs = []

def server():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen(1)
        while True:
            conn, addr = s.accept()
            with conn:
                p = subprocess.Popen(
                    ['python', sys.argv[0], '-worker'],
                    stdin=subprocess.PIPE, bufsize=0,
                    creationflags=subprocess.CREATE_NEW_CONSOLE)
                p.stdin.write(conn.share(p.pid))
                p.stdin.close()
                procs.append(p)

def cleanup():
    for p in procs:
        if p.poll() is None:
            p.terminate()

if __name__ == '__main__':
    if '-worker' in sys.argv[1:]:
        sys.exit(worker())

    atexit.register(cleanup)

    threading.Thread(target=server, daemon=True).start()

    tcli = []
    for msgs in (['spam', 'eggs'], ['foo', 'bar']):
        t = threading.Thread(target=client, args=(msgs,))
        t.start()
        tcli.append(t)

    for t in tcli:
        t.join()

    input('press enter to quit')

是否可以提供更多信息以更好地理解问题?一个进程一次只能附加到一个控制台(即conhost.exe实例),没有附加进程的控制台将自动关闭。您需要使用
creationflags=CREATE\u NEW\u CONSOLE
生成一个子进程。请阅读。@eryksun,我对您的代码所做的研究正是我想要的。如果您将此作为答案发布,我将接受它。您是否将数据从套接字中继到子进程的sdtin?您可以在
socketserver.threadingcpserver
的处理程序中执行此操作。我可以修改文档中的代码来演示。可以提供更多信息来更好地理解问题吗?一个进程一次只能附加到一个控制台(即conhost.exe实例),没有附加进程的控制台会自动关闭。您需要使用
creationflags=CREATE\u NEW\u CONSOLE
生成一个子进程。请阅读。@eryksun,我对您的代码所做的研究正是我想要的。如果您将此作为答案发布,我将接受它。您是否将数据从套接字中继到子进程的sdtin?您可以在
socketserver.threadingcpserver
的处理程序中执行此操作。我可以修改文档中的代码来演示它。