Python:与始终运行的子进程通信

标签 python python-2.7

我有以下情况。我有一个游戏和两个机器人,他们互相玩这个游戏。所有通信都是通过标准输入和标准输出完成的。现在我想编写一个引擎,让机器人相互对抗并决定哪个机器人赢得了比赛。为此,我需要从我的引擎运行机器人并通过标准输入和标准输出与它们进行通信。

因此,为了启动机器人,我做了以下操作:

from subprocess import Popen, PIPE, STDOUT
bot = Popen(['/path/to/bot1'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)

现在我想将游戏状态传输给机器人并请求我的机器人采取行动。因此,首先,我想向该进程写入一些文本行,之后我的引擎应该等待一段时间并从该进程中读取结果。请注意,该机器人始终在运行并且不会自行终止。

如何实现这一目标?

最佳答案

不幸的是,它可能不像从 bot.stdout 读取并写入 bot.stdin 那么容易。原因是,如果某些程序是子进程,则在程序执行完毕之前不会刷新到 STDOUT。解决这个问题的方法是在伪终端下生成它。以下是使用 pty 模块的示例:

bot1.py

#!/usr/bin/env python

name = raw_input("What is your name?\n")
print "Hello {}, my name is Bot1".format(name)
raw_input() # Bot2: Hello Bot1

bot2.py

#!/usr/bin/env python

raw_input() # Bot1: What is your name?
print "Bot2"
greeting = raw_input() # Bot1: Hello Bot2, my name is Bot1
print "Hello {}".format(greeting.split()[-1])

运行.py

#!/usr/bin/env python
import os
import pty
import termios

class Bot:

  def __init__(self, name, program):
    self.name = name

    # Fork a process in a pseudo-terminal
    self._pid, self._fd = pty.fork()

    if self._pid == 0:
      # Child process, replace with program
      os.execvp(program, [program])

    # Turn off echoing for child file descriptor, otherwise it will spew the
    # child's output to the parent's STDOUT.
    attribs = termios.tcgetattr(self._fd)
    attribs[3] = attribs[3] & ~termios.ECHO
    termios.tcsetattr(self._fd, termios.TCSANOW, attribs)

  def speak(self, bot):
    output = self.read()
    bot.write(output)

    print '{} -> {}: {}'.format(self.name, bot.name, output)

  def read(self):
    return os.read(self._fd, 1024).strip()

  def write(self, line):
    os.write(self._fd, line + "\n")

if __name__ == '__main__':

  bot1 = Bot('Bot1', './bot1.py')
  bot2 = Bot('Bot2', './bot2.py')

  # Bot1 -> Bot2: What is your name?
  bot1.speak(bot2)

  # Bot2 -> Bot1: Bot2
  bot2.speak(bot1)

  # Bot1 -> Bot2: Hello Bot2, my name is Bot1
  bot1.speak(bot2)

  # Bot2 -> Bot1: Hello Bot1
  bot2.speak(bot1)

输出

$ ./run.py 
Bot1 -> Bot2: What is your name?
Bot2 -> Bot1: Bot2
Bot1 -> Bot2: Hello Bot2, my name is Bot1
Bot2 -> Bot1: Hello Bot1

这是一个简单的示例,但希望它足以帮助您入门。

关于Python:与始终运行的子进程通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32720797/

相关文章:

python - Pypi的本地镜像,可以像Nexus一样按需下载包

python - 用于 Python 的简单、跨平台 MIDI 库

python-2.7 - 使用 random.choice 列出索引超出范围错误

python - 如何查看整个队列内容和自动队列推送

python - 添加除特定数字/python之外的数字之和

python - Bokeh 概念验证有效的动态图更新?

python-2.7 - 使用mayavi.mlab.mesh函数时Python脚本崩溃

python - 使用 for 循环的字典中的字典列表

python-2.7 - 在pygame中让多个球移动

python - Tensorflow NMT with Attention 教程——需要帮助理解损失函数