2

각 실행을 평가하기 위해 다중 처리 풀을 사용하여 콘솔 기반 게임의 다중 인스턴스 (연구 목적으로 자연스럽게 던전 크롤링 수프)를 실행하려고합니다.Python 하위 프로세스로 대화 형 셸 처리

이전에 비슷한 코드 (유전 알고리즘)를 평가하기 위해 풀을 사용한 적이 있는데, 각 프로세스를 분리하기 위해 subprocess.call을 사용했습니다. 그러나 dcss가 상당히 상호 작용하여 공유 서브 쉘을 갖는 것이 문제가되는 것 같습니다.

저는 일반적으로 이런 종류의 작업에 사용하는 코드가 있습니다. 크롤링은 GA를 던진 다른 애플리케이션을 대체합니다. 이보다 더 높은 대화식 셸을 처리하는 더 좋은 방법이 있습니까? 나는 각 인스턴스에 대한 화면을 시작하는 것으로 생각했지만 깨끗한 방법이 있다고 생각했습니다. 내 이해는 shell=True 하위 껍질을 산란되어야하지만 그것은 각 호출간에 공유되는 방식으로 하나 산란 것 같아요.

나는 게임을 실행하는 봇을 언급해야한다. 그래서 사용자의 실제적인 상호 작용이 발생하기를 원하지 않는다.

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

답변

1

할 수 있습니다 참으로 @napuzba의 대답과 같은 파일에 대한 준 표준 입력과 표준 출력 :

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

또 다른 옵션은 Popen 대신 call 사용하는 것입니다. 차이점은 Popen이 완료되지 않을 때 호출이 완료 될 때까지 기다리는 것입니다 ()

Popen을 사용하면 파일에 의존하지 않고 stdout 및 stderr을 개체 내에 유지 한 다음 나중에 사용할 수 있습니다. : 당신이,524을해야, 보조 노트에

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 

:

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

이 방법의 또 다른 잠재적 인 장점은 스레드 풀을 완료 기다리는 대신하지 않고는 popen의 여러 인스턴스를 실행할 수 있다는 것입니다 가능하다면3210 shell=True을 사용하고 사용하지 않으면 Popen은 목록 대신 문자열로 명령을 사용합니다. 당신을 위해 모든 코너 케이스 돌볼 것이다 수동으로 목록을 생성하지만, shlex를 사용하지 마십시오 예 :

Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
+0

그건 도움이 되겠지만, 나는 스레드 풀이 차단되어야한다고 확신합니다. GA에서 실행되므로 제어 루프의 다음 반복이 호출되기 전에 모든 구성원의 평가가 완료되어야합니다. – espais

+1

for 루프의'poll()'덕분에/차단 될 수 있습니다. 이 솔루션의 관심사는 실제로 하위 프로세스 실행을 시작하기 위해 스레드/스레드 풀을 직접 관리 할 필요가 없다는 것입니다. – Guillaume

1

고유 한 파일과 표준 입력, 표준 출력, 표준 에러를 지정은 각 통화에 대한 처리 :

import subprocess 
cmd = "" 
fout = open('stdout.txt','w') 
fin = open('stdin.txt','r') 
ferr = open('stderr.txt','w') 
subprocess.call(cmd, stdout=fout , stdin = fin , stderr=ferr) 
+0

내가 실제로 ttyrec을 캡처하는 것을 사용할 수 있을까? – espais

+0

글쎄, 나는 ttyrec에 익숙하지 않다. 그러나 파일 객체 나 파일과 같은 객체 인 'fin'으로부터 입력을 제공 할 수 있습니다. – napuzba

+0

리눅스에서 일하는 경우 -/dev/tty * 파일을 사용해 볼 수 있습니다. – napuzba