Opening a Python thread in a new console window

后端 未结 3 1467
终归单人心
终归单人心 2020-12-01 22:18

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 th

相关标签:
3条回答
  • 2020-12-01 22:21

    UPDATED ANSWER:

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

    "cmd.exe" - if using Windows, Windows ONLY recognizes double quotes.
    "/c" - says 'send the Return' after we send the 'dir'(for example) string.
    "start" - says open new console window...even if debugging in Pycharm :)
    f"command" - I use f-strings to send assemble strings Python3.6+
    (timeout optional)

    0 讨论(0)
  • 2020-12-01 22:31

    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.

    0 讨论(0)
  • 2020-12-01 22:39

    I agree with @stark a GUI is the way.

    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.

    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:

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

    To try it, run:

    $ python view.py
    
    0 讨论(0)
提交回复
热议问题