パイプを介して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"が問題を解決すると仮定しますが、なぜ "サブプロセス"で解決できないのか理解したい)