2017-01-05 10 views
1

gitコマンドを呼び出すスクリプトをいくつか書いていますが、gitがユーザ入力をブロックするページャを使って出力しようとすると問題が発生します。たとえば、次はlessで私をドロップ(私の知る限り)と私は継続するqにありますPythonのサブプロセスを使ったページャの処理

subprocess.Popen(['git', '--no-pager', 'diff', '--stat', '--cached', 'origin/master']).wait() 

:私はgitのを伝えることでページャを使用しないことを無効にすることができ

subprocess.Popen(['git', 'diff', '--stat', '--cached', 'origin/master']).wait() 

をこの特定のケースではいくつかの一般的な解決策がありますか(編集:つまり、それはすべてのためだけではなく、git)、私は出力をキャプチャすることができ、ページャではブロックできませんか、またはサブプロセスこの場合)ページャを自動的に使用しないようにしますか?

私はサブプロセスのstdinを閉じて、shell=True/False引数で試してみましたが、助けにはなりませんでした。


更新:
例えば出力が長いページを超える場合、 git diff --stat --cached origin/masterはページャであなたを着陸する予定。 git diff --stat --cached origin/master | catはしません。 gitはどうやって知っていますか?サブプロセスを使用してこの同じ効果を適用するにはどうすればよいですか?

+0

'--no-pager'は 'less'を使用しないでください。 gitの最新バージョンを使用していますか?あなたのgitコマンドは2.9.0でうまく動作します(lessなしで) –

+0

@MauriceMeyerはい、gitで動作します。しかし、私は、ページャを自動的に使用しようとする可能性のあるプログラムの一般的な解決策の後にいます。 – jozxyqk

答えて

2

gitPAGER環境変数に敏感で、次のように素敵な作品:

subprocess.Popen(['git', 'diff', '--stat', '--cached', 'origin/master'], env={'PAGER':'cat'}).wait() 
+0

ありがとう!しかし、私は根本原因を解決するのではなく、場合によってはgitを固定するだけです。 – jozxyqk

0

私の提案は、あなたが開かれることを期待ページャを終了するために必要なパイプのエスケープシーケンスになります。あなたは、この問題が発生することが予想されるときにエスケープ文字を送信することができ、パイプを作成するためにsubprocess.Popen()stdin引数を使用することができます。

p = subprocess.Popen(
     ['git', 'diff', '--stat', '--cached', 'origin/master'], 
     stdin=subprocess.PIPE) 

p.stdin.write('q') # q should quit most pagers 
p.wait() 

これは簡単にAの異なるポケットベルを処理するための関数やクラスに包ますることができ簡単な方法。そのままの状態で処理するのではなく、パイプに書き込まれている内容を変更するだけで、他の人が処理できるようになります。

0

2つの変更は、この問題を解決するように見える:

  1. stdoutstderrパイプを提供します。

    subprocess.Popen(['git', '--no-pager', 'diff', '--stat', '--cached', 'origin/master'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).wait() 
    

    しかし、この変更を行った後をWAIT使用しないでください:

    STDOUT = PIPEを使用して、および/またはstderr = PIPEと子プロセスがに十分な出力を生成するときにこれがデッドロックします警告OSパイプバッファがより多くのデータを受け入れるのを待つのをブロックするようにします。それを避けるには、()を使用してください。 from the docs

    代わりに...

  2. 使用communicate()

    p = subprocess.Popen(['git', '--no-pager', 'diff', '--stat', '--cached', 'origin/master'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    stdout, stderr = p.communicate() 
    print p.returncode 
    

    (また、標準出力と標準エラー出力をマージするstderr=subprocess.STDOUTを使用することができます)

私はgitはページャを使用するかどうかを決定するために次のようなものをやっていると思いますかそうでない場合: How do I detect whether sys.stdout is attached to terminal or not?

関連する問題