如何制作类Windows命令提示符的自定义控制台并实现无窗口交互?
首先,你遇到的两个核心问题:一是运行add.exe时弹出黑色控制台窗口,二是输入输出的交互逻辑不对导致结果不符合预期。下面分步骤帮你解决:
1. 消除弹出的控制台窗口
在Windows系统中,用subprocess.Popen运行控制台程序时,默认会创建新的控制台窗口。要禁用这个窗口,只需添加creationflags参数,指定subprocess.CREATE_NO_WINDOW(Python 3.7及以上版本支持)。
修改后的进程启动代码:
from subprocess import Popen, PIPE, CREATE_NO_WINDOW p = Popen(['add.exe'], stdout=PIPE, stdin=PIPE, stderr=PIPE, creationflags=CREATE_NO_WINDOW)
这样运行时就不会再弹出那个丑陋的黑窗口了。
2. 修复输入输出的交互逻辑
你的原代码直接写入b'4'和b'6',但input()函数是行缓冲的——它会等待用户输入一行(按下回车)才会返回。所以你需要在每个输入内容后加上换行符b'\n',让程序识别为输入完成。
另外,直接用p.stdout.read()会一直等待进程结束才读取全部输出,这在交互式场景下不适用。我们可以分步骤读取提示、写入输入,模拟真实的控制台交互:
from subprocess import Popen, PIPE, CREATE_NO_WINDOW # 启动进程,禁用控制台窗口,开启文本模式自动处理字节/字符串转换 p = Popen(['add.exe'], stdout=PIPE, stdin=PIPE, stderr=PIPE, text=True, creationflags=CREATE_NO_WINDOW) # 读取第一个输入提示 first_prompt = p.stdout.readline() print(first_prompt.strip()) # 输出: Enter 1st Number # 写入第一个数字,加换行并刷新缓冲区 p.stdin.write('4\n') p.stdin.flush() # 读取第二个输入提示 second_prompt = p.stdout.readline() print(second_prompt.strip()) # 输出: Enter 2nd Number # 写入第二个数字,加换行并刷新缓冲区 p.stdin.write('6\n') p.stdin.flush() # 读取最终的计算结果 result = p.stdout.readline() print(result.strip()) # 输出: a + b = 46 # 等待进程结束,清理资源 p.wait()
这里用text=True让subprocess自动处理字节和字符串的转换,代码更简洁易读。
3. 顺便修正add.exe的小问题
你提供的add.exe对应的Python代码里,input()获取的是字符串,直接a + b会做字符串拼接而非数值相加。如果要实现真正的加法,需要先转成整数:
a = int(input('Enter 1st Number: ')) b = int(input('Enter 2nd Number: ')) print(f'a + b = {a + b}')
修改后运行,得到的结果才是a + b = 10,而不是字符串拼接的46。
进阶:实现类似PyCharm的交互式控制台
如果要做更接近PyCharm的自定义控制台,需要处理实时的输入输出交互——可以用线程持续读取子进程的输出,避免主线程被阻塞。示例思路:
import threading from subprocess import Popen, PIPE, CREATE_NO_WINDOW def read_output(proc): while True: line = proc.stdout.readline() if not line: break print(f'[子进程输出] {line.strip()}') # 启动进程 p = Popen(['add.exe'], stdout=PIPE, stdin=PIPE, text=True, creationflags=CREATE_NO_WINDOW) # 启动线程读取输出,设为守护线程随主进程退出 output_thread = threading.Thread(target=read_output, args=(p,)) output_thread.daemon = True output_thread.start() # 处理用户输入,实时交互 while True: user_input = input('[输入] ') p.stdin.write(user_input + '\n') p.stdin.flush() # 检查进程是否结束,结束则退出循环 if p.poll() is not None: break
这样就能实现实时的输入输出交互,更接近专业控制台的体验。
内容的提问来源于stack exchange,提问作者Nikhil.Nixel

