6

I have a server program that runs through console. (Specifically, Bukkit MineCraft server) I'd like to be able to control this program and read the output. There is no GUI, so it shouldn't be too hard, right?

Anyway, I have never controlled a console in python and am totally stuck. Any suggestions?

P.S. I'm using Debian Linux, so that should simplify things a bit.

I've gotten a pretty good answer, but I also need one more thing. I want to have some way to print the FULL output of the program to the python console (Line by line is fine) and I need some way for commands in the console to be forwarded to the program.

jww
  • 97,681
  • 90
  • 411
  • 885
Eric Pauley
  • 1,709
  • 1
  • 20
  • 30
  • 2
    possible duplicate of [Python Script execute commands in Terminal](http://stackoverflow.com/questions/3730964/python-script-execute-commands-in-terminal) – Paul D. Waite Apr 19 '11 at 00:26
  • 1
    I'm not sure the above linked question is a duplicate, because that question doesn't talk about *interactive* programs. I'm sort of assuming that this server program is interactive in some way. – Greg Hewgill Apr 19 '11 at 00:29

2 Answers2

6

The canonical answer for a task like this is to use Pexpect.

Pexpect is a Python module for spawning child applications and controlling them automatically. Pexpect can be used for automating interactive applications such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup scripts for duplicating software package installations on different servers. It can be used for automated software testing. Pexpect is in the spirit of Don Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python require TCL and Expect or require C extensions to be compiled. Pexpect does not use C, Expect, or TCL extensions. It should work on any platform that supports the standard Python pty module. The Pexpect interface focuses on ease of use so that simple tasks are easy.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • This seems like a good method. I don't really need that much output, and this would appear to work perfectly for input. My one question is how will I know when the program stops running? – Eric Pauley Apr 19 '11 at 00:32
  • @Zonedabone: According to the [pexpect documentation](http://pexpect.sourceforge.net/pexpect.html), the `expect()` function raises an `EOF` or `TIMEOUT` exception when those events occur. – Greg Hewgill Apr 19 '11 at 22:14
1

You can try to create an interactive shell inside python, something like:

import sys
import os
import subprocess
from subprocess import Popen, PIPE
import threading


class LocalShell(object):
    def __init__(self):
        pass
    def run(self):
        env = os.environ.copy()
        p = Popen('open -a Terminal -n', stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT, shell=True, env=env)
        sys.stdout.write("Started Local Terminal...\r\n\r\n")

        def writeall(p):
            while True:
                # print("read data: ")
                data = p.stdout.read(1).decode("utf-8")
                if not data:
                    break
                sys.stdout.write(data)
                sys.stdout.flush()

        writer = threading.Thread(target=writeall, args=(p,))
        writer.start()

        try:
            while True:
                d = sys.stdin.read(1)
                if not d:
                    break
                self._write(p, d.encode())

        except EOFError:
            pass

    def _write(self, process, message):
        process.stdin.write(message)
        process.stdin.flush()
Shawn
  • 571
  • 7
  • 8