2016-07-26 12 views
0

パイプを介して1つずつコマンドを送ることで、Pythonインタプリタを制御したいとします。 g。 Pythonインタプリタに "hello"を印刷させ、3秒待ってからPythonインタプリタを "world"にします。Pythonインタプリタへのパイプ配管

なぜbashで以下のコード:

{ echo 'from sys import stdout' ; echo 'stdout.write("hello\n")' ; echo 'stdout.flush()' ; sleep 3 ; echo 'stdout.write("world\n")' ; echo 'stdout.flush()' ; } | python3.5 -u 

最初待機3秒、次に印刷次のコードに対し

hello 
world 

{ echo 'from sys import stdout' ; echo 'stdout.write("hello\n")' ; echo 'stdout.flush()' ; sleep 3 ; echo 'stdout.write("world\n")' ; echo 'stdout.flush()' ; } | while read -r l ; do echo $l ; done 

最初のプリント:

from sys import stdout 
stdout.write("hello\n") 
stdout.flush() 

を3秒待機し、最後に印刷:

stdout.write("world\n") 
stdout.flush() 

最後に、上記の例のような最初のPythonスクリプトから2番目のPythonインタプリタを制御したいとします( "hello"を表示、3秒待って、print "world")。これは "サブプロセス"のPythonモジュールで可能ですか?

以下のコード:上記のbashコードと同じ問題に

import logging 
from select import select 
from subprocess import Popen, PIPE, TimeoutExpired 
from time import sleep 
from threading import Thread 

logging.basicConfig(
    level=logging.DEBUG, 
    format="%(asctime)s %(message)s") 
logger = logging.getLogger() 

def read_stdout(proc): 
    stdout_closed, stderr_closed = False, False 

    while True: 
     rlist, wlist, xlist = select([proc.stdout, proc.stderr], [], [], 1.2) 
     if len(rlist) == 0: 
      logger.debug("timeout") 
      continue 
     if proc.stdout in rlist: 
      new_data = proc.stdout.read(1024) 
      logger.debug("new_data on stdout: %r" % new_data) 
      if len(new_data) == 0: 
       stdout_closed = True 
     if proc.stderr in rlist: 
      new_data = proc.stderr.read(1024) 
      logger.debug("new_data on stderr: %r" % new_data) 
      if len(new_data) == 0: 
       stderr_closed = True 
     if stdout_closed and stderr_closed: 
      break 

logger.debug("start") 
proc = Popen(
    #["bash", "-c", 'while read -r l ; do echo $l ; done'], 
    ["python", "-u"], 
    stdin=PIPE, 
    stdout=PIPE, 
    stderr=PIPE, 
    bufsize=0) 
thread = Thread(target=read_stdout, args=(proc,)) 
thread.start() 
proc.stdin.write(b'from sys import stdout\n') 
proc.stdin.write(b'stdout.write("hello\\n")\n') 
proc.stdin.write(b'stdout.flush()\n') 
proc.stdin.flush() 
sleep(3) 
proc.stdin.write(b'stdout.write("world\\n")\n') 
proc.stdin.write(b'stdout.flush()\n') 
proc.stdin.flush() 
proc.stdin.close() 
thread.join() 

結果:

popenの()は "パイソン-u" と呼ぶとき、ログ出力がある:

popenのは()を呼び出したときには
2016-07-27 00:46:05,208 start 
2016-07-27 00:46:06,411 timeout 
2016-07-27 00:46:07,612 timeout 
2016-07-27 00:46:08,213 new_data on stdout: b'hello\nworld\n' 
2016-07-27 00:46:08,216 new_data on stdout: b'' 
2016-07-27 00:46:08,216 new_data on stderr: b'' 

"のbash -c '-rl読みながら、エコー$ Lを行う;が実行'" は、その後、ログ出力は次のようになります。

2016-07-27 00:48:37,237 start 
2016-07-27 00:48:37,239 new_data on stdout: b'from sys import stdout\n' 
2016-07-27 00:48:37,239 new_data on stdout: b'stdout.write("hello\\n")\nstdout.flush()\n' 
2016-07-27 00:48:38,440 timeout 
2016-07-27 00:48:39,642 timeout 
2016-07-27 00:48:40,242 new_data on stdout: b'stdout.write("world\\n")\n' 
2016-07-27 00:48:40,242 new_data on stdout: b'stdout.flush()\n' 
2016-07-27 00:48:40,242 new_data on stderr: b'' 
2016-07-27 00:48:40,242 new_data on stdout: b'' 
2016-07-27 00:48:40,242 new_data on stderr: b'' 

Pythonインタプリタが送信されたコマンドをすぐに実行しない原因は何ですか?どういうわけか "サブプロセス"モジュールでこれを達成することは可能ですか? (私は "pexpect"が問題を解決すると仮定しますが、なぜ "サブプロセス"で解決できないのか理解したい)

答えて

0

"man python3"で観察された動作について、以下の説明があります。

非対話モードでは、入力全体が解析されてから実行されます。

関連する問題