I am trying to make a program that will launch both a view window (console) and a command line. In the view window, it would show constant updates, while the command line window would use raw_input()
to accept commands that affect the view window. I am thinking about using threads for this, but I have no idea how to launch a thread in a new console window. How would I do that?
我正在尝试创建一个程序,它将启动一个视图窗口(控制台)和一个命令行。在视图窗口中,它将显示常量更新,而命令行窗口将使用raw_input()接受影响视图窗口的命令。我正在考虑使用线程,但我不知道如何在新的控制台窗口中启动线程。我该怎么办?
2 个解决方案
#1
4
Rather than use a console or terminal window, re-examine your problem. What you are trying to do is create a GUI. There are a number of cross-platform toolkits including Wx and Tkinter that have widgets to do exactly what you want. A text box for output and an entry widget for reading keyboard input. Plus you can wrap them in a nice frame with titles, help, open/save/close, etc.
而不是使用控制台或终端窗口,重新检查您的问题。您要做的是创建一个GUI。有许多跨平台工具包,包括Wx和Tkinter,它们都有小部件可以完全按照你的需要进行操作。用于输出的文本框和用于读取键盘输入的条目小部件。另外,你可以将它们包装在一个漂亮的框架中,包括标题,帮助,打开/保存/关闭等。
#2
9
I agree with @stark a GUI is the way.
我同意@stark GUI的方式。
Purely for illustration here's a not recommended non-GUI way that shows how to do it using a thread, a subprocess, and a named pipe as IPC.
纯粹为了说明这里是一个不推荐的非GUI方式,它显示了如何使用线程,子进程和命名管道作为IPC。
There are two scripts:
有两个脚本:
-
entry.py
: accept commands from a user, do something with the command, pass it to the named pipe given at the command-line: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
: Launch the entry console, print constant updates in a thread, accept input from the named pipe and pass it to the updates thread: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)
To try it, run:
要试用它,请运行:
$ python view.py
#1
4
Rather than use a console or terminal window, re-examine your problem. What you are trying to do is create a GUI. There are a number of cross-platform toolkits including Wx and Tkinter that have widgets to do exactly what you want. A text box for output and an entry widget for reading keyboard input. Plus you can wrap them in a nice frame with titles, help, open/save/close, etc.
而不是使用控制台或终端窗口,重新检查您的问题。您要做的是创建一个GUI。有许多跨平台工具包,包括Wx和Tkinter,它们都有小部件可以完全按照你的需要进行操作。用于输出的文本框和用于读取键盘输入的条目小部件。另外,你可以将它们包装在一个漂亮的框架中,包括标题,帮助,打开/保存/关闭等。
#2
9
I agree with @stark a GUI is the way.
我同意@stark GUI的方式。
Purely for illustration here's a not recommended non-GUI way that shows how to do it using a thread, a subprocess, and a named pipe as IPC.
纯粹为了说明这里是一个不推荐的非GUI方式,它显示了如何使用线程,子进程和命名管道作为IPC。
There are two scripts:
有两个脚本:
-
entry.py
: accept commands from a user, do something with the command, pass it to the named pipe given at the command-line: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
: Launch the entry console, print constant updates in a thread, accept input from the named pipe and pass it to the updates thread: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)
To try it, run:
要试用它,请运行:
$ python view.py