multiple console windows for one Python script

前提是你 提交于 2019-12-12 04:26:06

问题


I've seen similar questions such as this one: keep multiple console windows open from batch.

However, I have a different situation. I do not want to run a different script in a different console window. My idea is to have socket running as a server and accepting all connections. When a connection is accepted, a new console window is created, and all in-coming and out-going data is shown there. Is that even possible?


回答1:


A process can only be attached to one console (i.e. instance of conhost.exe) at a time, and a console with no attached processes automatically closes. You would need to spawn a child process with creationflags=CREATE_NEW_CONSOLE.

The following demo script requires Windows Python 3.3+. It spawns two worker processes and duplicates each socket connection into the worker via socket.share and socket.fromshare. The marshaled socket information is sent to the child's stdin over a pipe. After loading the socket connection, the pipe is closed and CONIN$ is opened as sys.stdin to read standard input from the console.

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')


来源:https://stackoverflow.com/questions/39997081/multiple-console-windows-for-one-python-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!