一个 Python 脚本的多个控制台 windows
multiple console windows for one Python script
我见过类似的问题,例如:keep multiple console windows open from batch。
但是,我有不同的情况。我不想 运行 在不同的控制台 window 中使用不同的脚本。我的想法是将 socket 运行ning 作为服务器并接受所有连接。接受连接后,将创建一个新的控制台 window,并在那里显示所有传入和传出的数据。这可能吗?
一个进程一次只能附加到一个控制台(即 conhost.exe 的实例),没有附加进程的控制台会自动关闭。您需要使用 creationflags=CREATE_NEW_CONSOLE
生成一个 child 进程。
以下演示脚本需要 Windows Python 3.3+。它生成两个工作进程并通过 socket.share
和 socket.fromshare
将每个套接字连接复制到工作进程中。编组的套接字信息通过管道发送到 child 的 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')
我见过类似的问题,例如:keep multiple console windows open from batch。
但是,我有不同的情况。我不想 运行 在不同的控制台 window 中使用不同的脚本。我的想法是将 socket 运行ning 作为服务器并接受所有连接。接受连接后,将创建一个新的控制台 window,并在那里显示所有传入和传出的数据。这可能吗?
一个进程一次只能附加到一个控制台(即 conhost.exe 的实例),没有附加进程的控制台会自动关闭。您需要使用 creationflags=CREATE_NEW_CONSOLE
生成一个 child 进程。
以下演示脚本需要 Windows Python 3.3+。它生成两个工作进程并通过 socket.share
和 socket.fromshare
将每个套接字连接复制到工作进程中。编组的套接字信息通过管道发送到 child 的 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')