2017-01-28 9 views
1

sys.stdout.write()関数を使用した印刷に関する宿題の割り当てに問題があります。私がしなければならないのは、stdin/stdoutリダイレクションとパイプラインをサポートする単純なシェルを実装することです。下のコードでは、私のプログラム "ch.py​​"から、入力を要求する "%%"が、入力された式にパイプラインが含まれている間違った時刻に出力されるように見えるという問題があります。例えばsys.stdout.write()は、Pythonのパイプラインで間違ったタイミングで印刷します。

、私が入力した場合、 "-name ch.py​​を見つける| grepのインポートをxargsの"、私が取得したいことは次のとおりです。

%% 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

'evaluate()'に 'os.fork()'の結果として得られるpidも待つべきです。 'main()'の最初のforkに対してのみwaitpid()を呼び出します。したがって、 'pipe_count'> 0の場合、' evaluate() 'で作成されたプロセスのどれかを待つことに失敗します。 –

+0

あなたの助けてくれてありがとう!親と子が '評価する 'ことを逆転した後、親はすべての子どもたちが完了するのを待つことができ、問題は修正されました。 –

答えて

0

ここで固定コードは、サミ・レインに再度ありがとう。

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]) 
関連する問題