使用Python子进程处理交互式shell

时间:2017-04-22 02:24:08

标签: python python-2.7 shell subprocess python-multiprocessing

我正在尝试运行基于控制台的游戏的多个实例(地牢爬行石汤 - 自然地用于研究目的),使用多处理池来评估每次运行。

过去当我使用池来评估类似的代码(遗传算法)时,我使用subprocess.call来分离每个进程。但是,由于dcss非常具有交互性,因此共享子shell似乎存在问题。

我有通常用于此类事情的代码,爬行取代了我抛出GA的其他应用程序。有没有比这更好的方法来处理高度互动的shell?我考虑过为每个实例启动屏幕,但我认为有一种更清洁的方式。我的理解是shell=True应该产生一个子shell,但我想我是以每次调用之间共享的方式产生一个。

我应该提到我有一个运行该游戏的机器人,因此我不希望发生任何来自用户端的实际交互。

# Kick off the GA execution
pool_args = zip(trial_ids,run_types,self.__population)
pool.map(self._GAExecute, pool_args)

---

# called by pool.map 
def _GAExecute(self,pool_args):
  trial_id       = pool_args[0]
  run_type       = pool_args[1]
  genome         = pool_args[2]
  self._RunSimulation(trial_id)

# Call the actual binary
def _RunSimulation(self, trial_id):
  command = "./%s" % self.__crawl_binary
  name    = "-name %s" % trial_id
  rc      = "-rc %s" % os.path.join(self.__output_dir,'qw-%s'%trial_id,"qw -%s.rc"%trial_id)
  seed    = "-seed %d" % self.__seed
  cdir    = "-dir %s" % os.path.join(self.__output_dir,'qw-%s'%trial_id)

  shell_command = "%s %s %s %s %s" % (command,name,rc,seed,cdir)
  call(shell_command, shell=True)

2 个答案:

答案 0 :(得分:1)

使用每个调用的唯一文件句柄指定标准输入,标准输出和标准错误:

function airportArray(request, response) {
    var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
    response($.grep(airports, function(value) {
        return matcher.test(value.iata) || matcher.test(value.city) || matcher.test(value.airport);
    }));
}

答案 1 :(得分:1)

您确实可以将stdin和stdout关联到文件,如@napuzba的答案所示:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Web1</h2>

另一种选择是使用Popen代替call。不同之处在于呼叫等待完成(正在阻塞)而Popen没有,请参阅What's the difference between subprocess Popen and call (how can I use them)?

使用Popen,然后可以将stdout和stderr保留在对象中,然后在以后使用它们,而不必依赖文件:

fout = open('stdout.txt','w')
ferr = open('stderr.txt','w')
subprocess.call(cmd, stdout=fout, stderr=ferr)

此方法的另一个潜在优势是您可以运行多个Popen实例而无需等待完成而不是使用线程池:

p = subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
stderr = p.stderr.read()
stdout = p.stdout.read()

另外,如果可以的话,你应该avoid processes=[ subprocess.Popen(cmd1,stdout=subprocess.PIPE, stderr=subprocess.PIPE), subprocess.Popen(cmd2,stdout=subprocess.PIPE, stderr=subprocess.PIPE), subprocess.Popen(cmd3,stdout=subprocess.PIPE, stderr=subprocess.PIPE) ] for p in processes: if p.poll(): # process completed else: # no completion yet ,如果你不使用它,Popen希望列表作为命令而不是字符串。不要手动生成此列表,而是使用shlex来处理所有极端情况,例如:

shell=True
相关问题