subprocessreadline挂起等待EOF
我有一个简单的c ++程序,我试图通过python脚本来执行。 (我对编写脚本非常陌生),并且无法通过pipe道读取输出。 从我所看到的看来,如果没有EOF,readline()似乎不起作用,但是我希望能够在程序中间读取并且让脚本响应输出的内容。 而不是阅读输出,它只是挂起python脚本:
#!/usr/bin/env python import subprocess def callRandomNumber(): print "Running the random guesser" rng=subprocess.Popen("./randomNumber", stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) i=50 rng.stdin.write("%d\n" % i) output=rng.stdout.readline() output=rng.stdout.readline() callRandomNumber()
和c ++文件,它产生一个100之间的随机数,然后检查用户的猜测,直到他们猜测正确
#include<iostream> #include<cstdlib> using namespace std; int main(){ cout<<"This program generates a random number from 1 to 100 and asks the user to enter guesses until they succuessfully guess the number. It then tells the user how many guesses it took them"<<endl; srand(time(NULL)); int num=rand()%100; int guessCount=0; int guess=-1; cout<<"Please enter a number: "; cin>>guess; while(guess!=num){ if(guess>num){cout<<"That guess is too high. Please guess again: ";} else{cout<<"That guess is too low. Please guess again: ";} cin>>guess; guessCount++; } cout<<"Congratulations! You solved it in "<<guessCount<<" guesses!"<<endl; return 0; }
最终的目标是让脚本用二进制search来解决问题,但是现在我只想读取一行,而不必将其作为文件的结尾
正如@Ron Reiter指出的那样 ,你不能使用readline()
因为cout
不会隐式地打印换行符 – 你可能需要在这里使用std::endl
或"\n"
。
对于交互式的使用,当你不能改变子程序时, pexpect
模块提供了一些方便的方法(通常它可以免费解决:直接从/到terminalinput/输出(stdin / stdout之外)和块缓冲问题 ):
#!/usr/bin/env python import sys if sys.version_info[:1] < (3,): from pexpect import spawn, EOF # $ pip install pexpect else: from pexpect import spawnu as spawn, EOF # Python 3 child = spawn("./randomNumber") # run command child.delaybeforesend = 0 child.logfile_read = sys.stdout # print child output to stdout for debugging child.expect("enter a number: ") # read the first prompt lo, hi = 0, 100 while lo <= hi: mid = (lo + hi) // 2 child.sendline(str(mid)) # send number index = child.expect([": ", EOF]) # read prompt if index == 0: # got prompt prompt = child.before if "too high" in prompt: hi = mid - 1 # guess > num elif "too low" in prompt: lo = mid + 1 # guess < num elif index == 1: # EOF assert "Congratulations" in child.before child.close() break else: print('not found') child.terminate() sys.exit(-child.signalstatus if child.signalstatus else child.exitstatus)
它的工作,但它是一个二进制search因此(传统)可能有错误 。
这是一个类似的代码,使用subprocess
模块进行比较:
#!/usr/bin/env python from __future__ import print_function import sys from subprocess import Popen, PIPE p = Popen("./randomNumber", stdin=PIPE, stdout=PIPE, bufsize=1, # line-buffering universal_newlines=True) # enable text mode p.stdout.readline() # discard welcome message: "This program gener... readchar = lambda: p.stdout.read(1) def read_until(char): buf = [] for c in iter(readchar, char): if not c: # EOF break buf.append(c) else: # no EOF buf.append(char) return ''.join(buf).strip() prompt = read_until(':') # read 1st prompt lo, hi = 0, 100 while lo <= hi: mid = (lo + hi) // 2 print(prompt, mid) print(mid, file=p.stdin) # send number prompt = read_until(':') # read prompt if "Congratulations" in prompt: print(prompt) print(mid) break # found elif "too high" in prompt: hi = mid - 1 # guess > num elif "too low" in prompt: lo = mid + 1 # guess < num else: print('not found') p.kill() for pipe in [p.stdin, p.stdout]: try: pipe.close() except OSError: pass sys.exit(p.wait())
我很确定在你的C ++程序中添加换行会导致readlines返回。
你可能必须明确地closuresstdin
,所以subprocess会停止,我认为是你的代码发生了什么 – 这可以通过在terminal上运行top并检查randomnumber
的状态是否保持hibernate来validation在预期的执行时间之后使用0%的CPU。
简而言之,如果在rng=subprocess(...)
rng.stdin.close()
rng=subprocess(...)
调用之后添加rng.stdin.close()
,则可能会恢复正常。 另一个select是output=rng.communicate(stdin="%d\n" % i)
,分别查看stdout
和stderr
output[0]
和output[1]
。 你可以在这里find有关communicate
信息 。