Python 如何从单个脚本打开两个控制台
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19479504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I open two consoles from a single script
提问by K DawG
Apart from the scripts own console (which does nothing)I want to open two consoles and print the variables con1
and con2
in different consoles, How can I achieve this.
除了脚本自己的控制台(什么都不做)我想打开两个控制台con1
并con2
在不同的控制台中打印变量,我该如何实现这一点。
con1 = 'This is Console1'
con2 = 'This is Console2'
I've no idea how to achieve this and spent several hours trying to do so with modules such as subprocess
but with no luck. I'm on windows by the way.
我不知道如何实现这一点,并花了几个小时尝试使用诸如subprocess
但没有运气的模块来做到这一点。顺便说一下,我在窗户上。
Edit:
编辑:
Would the threading
module do the job? or is multiprocessing
needed?
该threading
模块能完成这项工作吗?还是multiprocessing
需要?
Eg:
例如:
采纳答案by jfs
If you don't want to reconsider your problem and use a GUIsuch as in @Kevin's answerthen you could use subprocess
module to start two new consoles concurrently and display two given strings in the opened windows:
如果您不想重新考虑您的问题并使用@Kevin's answer 中的 GUI,那么您可以使用subprocess
module 同时启动两个新控制台并在打开的窗口中显示两个给定的字符串:
#!/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")
Here's a simplified version that doesn't rely on CREATE_NEW_CONSOLE
:
这是一个不依赖于的简化版本CREATE_NEW_CONSOLE
:
#!/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()
回答by Paulo Scardine
Do you know about screen/tmux?
你知道 screen/tmux 吗?
How about tmuxp? For example, you can try to run cat
in split panes and use "sendkeys" to send output (but dig the docs, may be there is even easier ways to achieve this).
tmuxp怎么样?例如,您可以尝试cat
在拆分窗格中运行并使用“sendkeys”发送输出(但挖掘文档,可能有更简单的方法来实现这一点)。
As a side bonus this will work in the text console or GUI.
作为附带奖励,这将在文本控制台或 GUI 中工作。
回答by Kevin
You can get something liketwo consoles using two Tkinter Text widgets.
您可以使用两个 Tkinter Text 小部件获得类似两个控制台的东西。
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")
Result:
结果:
回答by marxin
I don't know if it suits you, but you can open two Python interpreters using Windows start
command:
我不知道它是否适合您,但是您可以使用 Windowsstart
命令打开两个 Python 解释器:
from subprocess import Popen
p1 = Popen('start c:\python27\python.exe', shell=True)
p2 = Popen('start c:\python27\python.exe', shell=True)
Of course there is problem that now Python runs in interactive mode which is not what u want (you can also pass file as parameter and that file will be executed).
当然有一个问题,现在 Python 以交互模式运行,这不是你想要的(你也可以将文件作为参数传递,该文件将被执行)。
On Linux I would try to make named pipe, pass the name of the file to python.exe and write python commands to that file. 'Maybe' it will work ;)
在 Linux 上,我会尝试创建命名管道,将文件名传递给 python.exe 并将 python 命令写入该文件。'也许'它会起作用;)
But I don't have an idea how to create named pipe on Windows. Windows API ... (fill urself).
但我不知道如何在 Windows 上创建命名管道。Windows API ...(填写自己)。
回答by JDOaktown
I used jfs' response. Here is my embellishment/theft of jfs response. This is tailored to run on Win10 and also handles Unicode:
我使用了 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)