Python 如何从一个脚本打开两个控制台

Python 如何从一个脚本打开两个控制台,python,python-2.7,Python,Python 2.7,除了脚本自己的控制台(什么也不做)之外,我想打开两个控制台,在不同的控制台中打印变量con1和con2,我如何实现这一点 con1 = 'This is Console1' con2 = 'This is Console2' 我不知道如何实现这一点,花了几个小时尝试使用子流程等模块来实现,但运气不佳。顺便说一下,我在窗户上 编辑: threading模块会完成这项工作吗?还是需要多处理 例如: 你知道screen/tmux吗 怎么样?例如,您可以尝试在拆分窗格中运行cat,并使用“sendk

除了脚本自己的控制台(什么也不做)之外,我想打开两个控制台,在不同的控制台中打印变量
con1
con2
,我如何实现这一点

con1 = 'This is Console1'
con2 = 'This is Console2'
我不知道如何实现这一点,花了几个小时尝试使用
子流程
等模块来实现,但运气不佳。顺便说一下,我在窗户上


编辑:
threading
模块会完成这项工作吗?还是需要
多处理

例如:


你知道screen/tmux吗

怎么样?例如,您可以尝试在拆分窗格中运行
cat
,并使用“sendkeys”发送输出(但是挖掘文档,可能有更简单的方法来实现这一点)

作为附带的好处,这将在文本控制台或GUI中工作。

您可以使用两个Tkinter文本小部件获得类似于两个控制台的东西

from Tkinter import *
import threading

class FakeConsole(Frame):
    def __init__(self, root, *args, **kargs):
        Frame.__init__(self, root, *args, **kargs)

        #white text on black background,
        #for extra versimilitude
        self.text = Text(self, bg="black", fg="white")
        self.text.pack()

        #list of things not yet printed
        self.printQueue = []

        #one thread will be adding to the print queue, 
        #and another will be iterating through it.
        #better make sure one doesn't interfere with the other.
        self.printQueueLock = threading.Lock()

        self.after(5, self.on_idle)

    #check for new messages every five milliseconds
    def on_idle(self):
        with self.printQueueLock:
            for msg in self.printQueue:
                self.text.insert(END, msg)            
                self.text.see(END)
            self.printQueue = []
        self.after(5, self.on_idle)

    #print msg to the console
    def show(self, msg, sep="\n"):
        with self.printQueueLock:
            self.printQueue.append(str(msg) + sep)

#warning! Calling this more than once per program is a bad idea.
#Tkinter throws a fit when two roots each have a mainloop in different threads.
def makeConsoles(amount):
    root = Tk()
    consoles = [FakeConsole(root) for n in range(amount)]
    for c in consoles:
        c.pack()
    threading.Thread(target=root.mainloop).start()
    return consoles

a,b = makeConsoles(2)

a.show("This is Console 1")
b.show("This is Console 2")

a.show("I've got a lovely bunch of cocounts")
a.show("Here they are standing in a row")

b.show("Lorem ipsum dolor sit amet")
b.show("consectetur adipisicing elit")
结果:

如果您不想在中这样做,则可以使用
子流程
模块同时启动两个新控制台,并在打开的窗口中显示两个给定字符串:

#!/usr/bin/env python3
import sys
import time
from subprocess import Popen, PIPE, CREATE_NEW_CONSOLE

messages = 'This is Console1', 'This is Console2'

# open new consoles
processes = [Popen([sys.executable, "-c", """import sys
for line in sys.stdin: # poor man's `cat`
    sys.stdout.write(line)
    sys.stdout.flush()
"""],
    stdin=PIPE, bufsize=1, universal_newlines=True,
    # assume the parent script is started from a console itself e.g.,
    # this code is _not_ run as a *.pyw file
    creationflags=CREATE_NEW_CONSOLE)
             for _ in range(len(messages))]

# display messages
for proc, msg in zip(processes, messages):
    proc.stdin.write(msg + "\n")
    proc.stdin.flush()

time.sleep(10) # keep the windows open for a while

# close windows
for proc in processes:
    proc.communicate("bye\n")
这里有一个简化版本,它不依赖于
CREATE\u NEW\u控制台

#!/usr/bin/env python
"""Show messages in two new console windows simultaneously."""
import sys
import platform
from subprocess import Popen

messages = 'This is Console1', 'This is Console2'

# define a command that starts new terminal
if platform.system() == "Windows":
    new_window_command = "cmd.exe /c start".split()
else:  #XXX this can be made more portable
    new_window_command = "x-terminal-emulator -e".split()

# open new consoles, display messages
echo = [sys.executable, "-c",
        "import sys; print(sys.argv[1]); input('Press Enter..')"]
processes = [Popen(new_window_command + echo + [msg])  for msg in messages]

# wait for the windows to be closed
for proc in processes:
    proc.wait()

我不知道它是否适合您,但您可以使用Windows
start
命令打开两个Python解释器:

from subprocess import Popen
p1 = Popen('start c:\python27\python.exe', shell=True)
p2 = Popen('start c:\python27\python.exe', shell=True)
当然,有一个问题是,现在Python在交互模式下运行,这不是您想要的(您也可以将文件作为参数传递,该文件将被执行)

在Linux上,我会尝试创建命名管道,将文件名传递给python.exe,并将python命令写入该文件也许‘它会起作用;)


但我不知道如何在Windows上创建命名管道。Windows API。。。(自填)。

pymux

pymux接近您想要的:

不幸的是,它主要是取代
tmux
的CLI工具,并且还没有一个像样的编程API

但是,如果您对此持认真态度,那么对其进行黑客攻击以公开该API可能是最可靠的选择

自述文件说:

pymux的一部分可以成为一个库,因此任何prompt_toolkit应用程序都可以嵌入vt100终端。(想象一下,pyvim中嵌入了一个终端仿真器。)


我使用了jfs的回应。以下是我对jfs回应的修饰/窃取。 这是为在Win10上运行而定制的,还可以处理Unicode:

# https://stackoverflow.com/questions/19479504/how-can-i-open-two-consoles-from-a-single-script
import sys, time, os, locale
from subprocess import Popen, PIPE, CREATE_NEW_CONSOLE

class console(Popen)  :
    NumConsoles = 0
    def __init__(self, color=None, title=None):
        console.NumConsoles += 1

        cmd = "import sys, os, locale"
        cmd += "\nos.system(\'color " + color + "\')" if color is not None else ""
        title = title if title is not None else "console #" + str(console.NumConsoles)
        cmd += "\nos.system(\"title " + title + "\")"
        # poor man's `cat`
        cmd += """
print(sys.stdout.encoding, locale.getpreferredencoding() )
endcoding = locale.getpreferredencoding()
for line in sys.stdin:
    sys.stdout.buffer.write(line.encode(endcoding))
    sys.stdout.flush()
"""

        cmd = sys.executable, "-c", cmd
        # print(cmd, end="", flush=True)
        super().__init__(cmd, stdin=PIPE, bufsize=1, universal_newlines=True, creationflags=CREATE_NEW_CONSOLE, encoding='utf-8')


    def write(self, msg):
        self.stdin.write(msg + "\n" )

if __name__ == "__main__":
    myConsole = console(color="c0", title="test error console")
    myConsole.write("Thank you jfs. Cool explanation")
    NoTitle= console()
    NoTitle.write("default color and title! This answer uses Windows 10")
    NoTitle.write(u"♥♥♥♥♥♥♥♥")
    NoTitle.write("♥")
    time.sleep(5)
    myConsole.terminate()
    NoTitle.write("some more text. Run this at the python console.")
    time.sleep(4)
    NoTitle.terminate()
    time.sleep(5)

如果您在windows上,则可以使用Win32 console模块为线程或子进程输出打开第二个控制台。如果您在windows上,这是最简单、最容易的方法

下面是一个示例代码:

import win32console
import multiprocessing

def subprocess(queue):
    win32console.FreeConsole() #Frees subprocess from using main console
    win32console.AllocConsole() #Creates new console and all input and output of subprocess goes to this new console
    while True:
        print(queue.get())
        #prints any output produced by main script passed to subprocess using queue

queue = multiprocessing.Queue()
multiprocessing.Process(Target=subprocess, args=[queue]).start()
while True:
    print("Hello World")
    #and whatever else you want to do in ur main process
您也可以通过线程来实现这一点。如果需要队列功能,则必须使用,因为线程模块没有队列


这是一个

只有一个控制台。它确实是可能的。您可以有一个脚本作为一个新的子进程启动,或者您可以获得一个本机库。但你肯定能做到。这可能会有帮助:(可能重复)我不理解你的编辑。我看不出子流程不符合您的要求的任何原因。为什么它不显示任何文本?@KDawG:我已经在Python 3.3 windows 8上测试过了。它的工作原理是这样的:两个控制台弹出消息,它们在10秒内关闭。在Python 2.7Windows 7用户界面上,代码应该可以正常工作,无需更改。当我运行这个程序时,两个控制台窗口在屏幕上闪烁并快速关闭。十秒钟后,我得到了
OSError:[Errno 22]无效参数
。(见完整堆栈跟踪)@Kevin:你是如何运行脚本的?你能试试吗。使用脚本2在目录中打开控制台。运行
py_script.py
Yes,结果相同。