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

8

我正在尝试制作一个程序,它可以启动一个视图窗口(控制台)和一个命令行。在视图窗口中,它会显示持续的更新,而命令行窗口将使用raw_input()来接受影响视图窗口的命令。我考虑使用线程来实现这一点,但我不知道如何在新的控制台窗口中启动线程。我应该怎么做呢?


3
不确定您是否能够承担这个任务,但是各个平台之间存在巨大的差异。最重要的是,Windows控制台与UNIX终端不同。您使用的是哪个平台? - Martijn Pieters
我想知道如何在Windows和UNIX/Linux/Mac上实现,并使用sys.platform来实现可移植性。 - elijaheac
你可以使用多个进程和命名管道吗?如果你选择使用多个进程的策略,那么就需要考虑很多进程间通信的策略。你使用哪个平台? - Mads Buch
我想知道如何在Windows和UNIX/Linux/Mac上进行操作。 - elijaheac
写更新的程序是从哪里来的?你能控制它吗? - jfs
显示剩余2条评论
3个回答

12

我同意@stark的观点,GUI是一种方法。

仅作说明,这里有一个不推荐的非GUI方式,展示如何使用线程、子进程和命名管道作为IPC来完成它。

有两个脚本:

  • entry.py: accept commands from a user, do something with the command, pass it to the named pipe given at the command-line:

    #!/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:

    #!/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

我认为我已经理解了你代码的要点。所以为了确认,当你启动子进程 p = launch_entry_console(named_pipe) 并且使用 with open(named_pipe) as file 开始读取文件时,这个读取是在 p 在后台运行的情况下完成的吗?也就是说,如果我想在打开管道时读取到某个文本“stop”并终止 p,我已经可以使用这个方案了。 - user6039682
是的,当您从命名管道读取时,“p”进程正在运行。 - jfs
在Windows中,您可以使用console = ["cmd.exe", "/c", "start"]start使Windows打开一个新窗口。此外,我更喜欢引用COMSPEC环境变量并使用大写字母,例如console = [os.environ.get("COMSPEC", "CMD.EXE"), "/C", "START"],但这只是我的风格。当然,我同意GUI比所有这些都更好的解决方案。 - wecsam

7

与其使用控制台或终端窗口,不如重新审视您的问题。您要做的是创建一个GUI界面。有许多跨平台工具包,包括Wx和Tkinter,它们有适合您需要的小部件。一个用于输出的文本框和一个用于读取键盘输入的输入小部件。此外,您可以将它们包装在一个漂亮的框架中,包括标题、帮助、打开/保存/关闭等功能。


1

更新的答案:

import subprocess
command = "dir"
subprocess.run(["cmd.exe", "/c", "start", f"{command}"], timeout=15)

"cmd.exe" - 如果使用Windows系统,则只能识别双引号。
"/c" - 表示在发送'dir'(例如)字符串后,发送回车键。
"start" - 表示打开新的控制台窗口,即使在Pycharm中进行调试 :)
f"command" - 我使用f-strings将汇编字符串发送到Python3.6+。
(timeout可选)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接