I have a Python script that runs three compiled programs and makes them communicate via standard I/O. This is my first time using pexpect. My program runs very slowly. Is there anything that I can do to speed up the program? If not, I can try to do it with C/C++ pipe/fork.

import pexpect
import os

Checker = pexpect.spawn("./checker") # a turn based game
Player = [0,1]
Player[1] = pexpect.spawn("./player1") # same game with computer player
Player[0] = pexpect.spawn("./player2") # same game with computer player

# tell each player wether it is 1st or 2nd player
Player[1].sendline("1") # 
Player[1].expect("\n")  # delete input from before
Player[0].expect("\n")  # delete input from before

player = 1
while True:

    Player[player].expect("\n") # wait for current player's move(a line)
    move = Player[player].before.strip() # read current player's move
    print move

    if not Checker.isalive(): # this does not run in usual
        print "endgame checker died"
    Checker.expect("\n") # delete input from before
    Checker.expect("\n") # wait checker's response
    check = Checker.before.strip() # read the response
    if check != "": # checker will send an empty line if move is valid and game didn't end
        print "endgame   ", check # otherwise response is other player's number
        Player[0].kill(0) # kill all

    player = (player+1) %2 # change current player
    if not Player[player].isalive(): # this does not run in usual
        print "endgame" + player + "died"

    Player[player].expect("\n")  # delete input from before
  • \$\begingroup\$ Can you show us the code for the checker and players? \$\endgroup\$ Apr 1 '16 at 16:29

here are a few ways to cleanup the code and make it more readable. This does not really go over functionality too much as I am not super familiar with pexpect or your other program you are trying to interface with. There are probably some optimizations to do the While loop in your program especially around the end where you are changing the player you are looping on but since I am unfamiliar I will leave that alone.

Without seeing the code or having a better understanding of how the checker/player works, this will be the best I can give for now.

  • Unused imports aren't a terrible thing, but aren't really a good thing either, best to remove them.

  • It doesn't seem like any naming convention is really being strictly followed. For example you have Checker = pexpect.spawn("./checker") but then later are doing check = Checker.before.strip(). It is best to follow PEP8 and stick with the snakecase naming convention. So it would be checker = pexpect.spawn("./checker")

  • Similarly named variables can be confusing. You have Player and player but they are different things. Best to be more specific, player_list and current_player would be better.

  • Use list literals instead of creating a list with aribitrary values then indexing in. You could rewrite

    Player = [0,1]
    Player[1] = pexpect.spawn("./player1")
    Player[0] = pexpect.spawn("./player2")


    Player = [pexpect.spawn("./player2"),pexpect.spawn("./player1")]

    but that looks a little backwards, so I am gonna change all the indexing so player 1 is in index 0.

    player_list = [pexpect.spawn("./player1"), pexpect.spawn("./player2")]
  • Use string interpolation

    print "endgame   ", check

    Would become

    print "endgame {}".format(check)


    print "endgame" + player + "died"

    would become

    print "endgame {} died".format(player)
  • Use the natural feel of booleans instead of check != "" where you should have done if check. Python will check for None and "" for you.

Here is my version of the script that should function the same.

import pexpect

checker = pexpect.spawn("./checker")
player_list = [pexpect.spawn("./player1"), pexpect.spawn("./player2")]

player_list[0].expect("\n")  # delete input from before
player_list[1].expect("\n")  # delete input from before

current_player_idx = 0
while True:
    player = player_list[current_player_idx]
    move = player.before.strip()
    print move

    if not checker.isalive():
        print "endgame checker died"
    checker.expect("\n") # delete input from before
    check = checker.before.strip()
    if check:
        # Really have no idea what you are trying to do in here, so I am leaving it alone. 
        print "endgame {}".format(check)

    # If I understand correctly, you are trying to see if the OTHER player is still alive.
    current_player_idx = (current_player_idx + 1) % 2
    if not player_list[current_player_idx].isalive():
        print "endgame {} died".format(current_player_idx)
        player_list[current_player_idx].expect("\n")  # delete input from before
  • \$\begingroup\$ There was not any bugs in program flow. Everything worked as I expected. I will change variable names and print formatted strings as you said. \$\endgroup\$ Apr 3 '16 at 22:17
  • \$\begingroup\$ Why even put that code I'm there then? It is possible it was just an indentation error. However putting a break before statements like that means those statements will never ever be executed. \$\endgroup\$ Apr 3 '16 at 22:19
  • \$\begingroup\$ Lines after break are not in the if block. I am going to include some comments in the code so that you can understand what it does. \$\endgroup\$ Apr 3 '16 at 22:34
  • \$\begingroup\$ I haven't changed the code. \$\endgroup\$ Apr 3 '16 at 22:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.