一尘不染

在新的控制台窗口中打开Python线程

python

我正在尝试制作一个程序,该程序将同时启动查看窗口(控制台)和命令行。在视图窗口中,它将显示不断的更新,而命令行窗口将用于raw_input()接受影响视图窗口的命令。我正在考虑为此使用线程,但是我不知道如何在新的控制台窗口中启动线程。我该怎么办?


阅读 173

收藏
2020-12-20

共1个答案

一尘不染

重新检查您的问题,而不是使用控制台或终端窗口。您试图做的是创建一个GUI。有许多跨平台的工具包,包括Wx和Tkinter,它们的小部件可以完全满足您的需求。用于输出的文本框和用于读取键盘输入的输入小部件。另外,您可以将它们包装在带有标题,帮助,打开/保存/关闭等的漂亮框架中。

我同意@stark的GUI是这样的。

纯粹出于说明目的,这是一种不建议使用的非GUI方式,该方式显示了如何使用线程,子进程和命名管道(如IPC)来执行此操作。

有两个脚本:

entry.py:接受用户的命令,对命令进行处理,然后将其传递给命令行中指定的命名管道:

#!/usr/bin/env python
import sys

print 'entry console'
with open(sys.argv[1], 'w') as file:
    for command in iter(lambda: raw_input('>>> '), ''):
        print ''.join(reversed(command)) # do something with it
        print >>file, command # pass the command to view window
        file.flush()

view.py:启动入口控制台,在线程中打印常量更新,接受来自命名管道的输入,并将其传递给更新线程:

#!/usr/bin/env python
import os
import subprocess
import sys
import tempfile
from Queue import Queue, Empty
from threading import Thread

def launch_entry_console(named_pipe):
    if os.name == 'nt': # or use sys.platform for more specific names
        console = ['cmd.exe', '/c'] # or something
    else:
        console = ['xterm', '-e'] # specify your favorite terminal
                                  # emulator here

    cmd = ['python', 'entry.py', named_pipe]
    return subprocess.Popen(console + cmd)

def print_updates(queue):
    value = queue.get() # wait until value is available

    msg = ""
    while True:
        for c in "/-\|":
            minwidth = len(msg) # make sure previous output is overwritten
            msg = "\r%s %s" % (c, value)
            sys.stdout.write(msg.ljust(minwidth))
            sys.stdout.flush()

            try:
                value = queue.get(timeout=.1) # update value
                print
            except Empty:
                pass

print 'view console'
# launch updates thread
q = Queue(maxsize=1) # use queue to communicate with the thread
t = Thread(target=print_updates, args=(q,))
t.daemon = True # die with the program
t.start()

# create named pipe to communicate with the entry console
dirname = tempfile.mkdtemp()
named_pipe = os.path.join(dirname, 'named_pipe')
os.mkfifo(named_pipe) #note: there should be an analog on Windows
try:
    p = launch_entry_console(named_pipe)
    # accept input from the entry console
    with open(named_pipe) as file:
        for line in iter(file.readline, ''):
            # pass it to 'print_updates' thread
            q.put(line.strip()) # block until the value is retrieved
    p.wait()
finally:
    os.unlink(named_pipe)
    os.rmdir(dirname)

要尝试,请运行:

$ python view.py
2020-12-20