Ich möchte einen Python-Interpreter steuern, indem ich Befehle nacheinander über eine Pipe an e. G. Lassen Sie den Python-Interpreter "Hallo" drucken, warten Sie 3 Sekunden und lassen Sie dann den Python-Interpreter "Welt" drucken.Piping-Befehle in einen Python-Interpreter
Warum funktioniert der folgende Code in einer 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
zuerst wartet 3 Sekunden und dann druckt:
hello
world
während den folgenden Code:
{ 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
Erstdrucke:
from sys import stdout
stdout.write("hello\n")
stdout.flush()
wartet dann 3 Sekunden und schließlich druckt:
stdout.write("world\n")
stdout.flush()
?
Am Ende möchte ich einen zweiten Python-Interpreter von einem ersten Python-Skript wie im obigen Beispiel steuern (print "Hallo", warte 3 Sekunden, drucke "Welt"). Ist das mit dem Python-Modul "Subprozess" möglich?
Der folgende Code:
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()
Ergebnisse in dem gleichen Problem wie der Bash-Code oben:
Wenn Popen() ruft "Python -u", dann wird die Protokollausgabe ist:
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''
während bei Popen() ruft "bash -c 'während gelesen -rl; do echo $ l; done'", dann wird die Protokollausgabe ist:
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''
Was ist der Grund dafür, dass der Python-Interpreter den Befehl, der an ihn gesendet wird, nicht sofort ausführt? Kann das irgendwie mit dem Modul "Subprozess" erreicht werden? (Ich gehe davon aus „pexpect“, um das Problem zu lösen, aber ich mag verstehen, wenn oder warum nicht „Subprozess“ es lösen kann.)