我在与使用sys.stdout.write()函数打印相关的家庭作业中遇到问题。我要做的是实现一个支持stdin / stdout重定向和管道的简单shell。在下面的代码中,从我的程序" ch.py",问题是" %%"当输入的表达式包含管道时,要求输入似乎在错误的时间打印。
例如,如果我输入"找到-name ch.py | xargs grep import",我想得到的是:
%% find -name ch.py | xargs grep import
import os
import sys
import shlex
%%
但实际上我得到的是:
%% find -name ch.py | xargs grep import
%% import os
import sys
import shlex
由于当输入不包含管道时问题不存在,因为" ls"或者" cat ch.py",我想我的主进程在继续之前不会等待所有子进程完成。我试着调用" os.waitpid()"与其他组合的参数或使用" os.wait()"相反,似乎没有什么能解决这个问题。
有人可以帮助我理解我错了吗?
import os
import sys
import shlex
def main():
while True:
sys.stdout.write("%% ")
sys.stdout.flush()
user_input = sys.stdin.readline()
if user_input:
parsed_input, to_write = parse(user_input)
else: # user pressed Ctrl+D, exit program
sys.stdout.write("Bye!\n")
sys.exit(0)
pid = os.fork()
if pid == 0: # EVALUATION PROCESS
if to_write: # if stdout redirection
os.dup2(to_write, 1) # write in file instead of stdout
os.close(to_write)
evaluate(parsed_input, len(parsed_input)-1)
elif pid > 0: # MAIN PROCESS
os.waitpid(pid, 0) # wait for evaluation to complete
def evaluate(parsed_input, pipe_count):
if pipe_count == 0:
# execute leftmost command of the expression
os.execvp(parsed_input[0][0], parsed_input[0])
elif pipe_count > 0:
r, w = os.pipe()
pid = os.fork()
if pid == 0: # CHILD
os.close(w)
os.dup2(r, 0) # read from pipeline instead of stdin
os.close(r)
# execute right side of the pipeline
os.execvp(parsed_input[-1][0], parsed_input[-1])
elif pid > 0: # PARENT
os.close(r)
os.dup2(w, 1) # write in pipeline instead of stdout
os.close(w)
# evaluate left side of the pipeline
evaluate(parsed_input[:-1], pipe_count-1)
答案 0 :(得分:0)
这里是固定代码,再次感谢Sami Laine。
def evaluate(parsed_input, pipe_count):
if pipe_count == 0:
# execute leftmost command of the expression
os.execvp(parsed_input[0][0], parsed_input[0])
elif pipe_count > 0:
r, w = os.pipe()
pid = os.fork()
if pid == 0: # CHILD
os.close(r)
os.dup2(w, 1) # write in pipeline instead of stdout
os.close(w)
# evaluate left side of the pipeline
evaluate(parsed_input[:-1], pipe_count-1)
elif pid > 0: # PARENT
os.close(w)
os.dup2(r, 0) # read from pipeline instead of stdin
os.close(r)
os.waitpid(pid, 0) # wait for children to complete
# execute right side of the pipeline
os.execvp(parsed_input[-1][0], parsed_input[-1])