7

このコードは、Python 2.5.1で実行すると、「AttributeError:'Popen'オブジェクトには属性'fileno'がありません」を生成します。

コード:

def get_blame(filename): 
    proc = []
    proc.append(Popen(['svn', 'blame', shellquote(filename)], stdout=PIPE))
    proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)
    proc.append(Popen(['tr', r"'\040'", r"';'"], stdin=proc[-1]), stdout=PIPE)
    proc.append(Popen(['cut', r"-d", r"\;", '-f', '3'], stdin=proc[-1]), stdout=PIPE)
    return proc[-1].stdout.read()

スタック:

function walk_folder in blame.py at line 55
print_file(os.path.join(os.getcwd(), filename), path)

function print_file in blame.py at line 34
users = get_blame(filename)

function get_blame in blame.py at line 20
proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)

function __init__ in subprocess.py at line 533
(p2cread, p2cwrite,

function _get_handles in subprocess.py at line 830
p2cread = stdin.fileno()

このコードは、この使用法を説明しているPythonドキュメントで機能しているはずです。

4

5 に答える 5

10

三つのこと

まず、あなたの()は間違っています。

次に、の結果はsubprocess.Popen()ファイルではなくプロセスオブジェクトです。

proc = []
proc.append(Popen(['svn', 'blame', shellquote(filename)], stdout=PIPE))
proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)

の値はファイルでproc[-1]はなく、ファイルを含むプロセスです。

proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1].stdout, stdout=PIPE))

第三に、それをすべて実行しないでください。シェルtrcutジャンクを実行しないでください。速度が低下する可能性があります。trPythonでと処理を記述cutします-それはより速くそしてより簡単です。

于 2009-04-22T16:15:09.047 に答える
3

スクリプトには奇妙なことがいくつかありますが、

  • 各プロセスをリストに保存するのはなぜですか?単に変数を使用する方がはるかに読みやすいのではないでしょうか。すべてを削除すると.append()s、構文エラーが明らかになります。Popenの代わりにstdout=PIPEをappend引数に数回渡しました。

    proc.append(Popen(...), stdout=PIPE)
    

    したがって、ストレートリライト(まだエラーがありますが、後で説明します)は次のようになります。

    def get_blame(filename): 
        blame = Popen(['svn', 'blame', shellquote(filename)], stdout=PIPE)
        tr1 = Popen(['tr', '-s', r"'\040'"], stdin=blame, stdout=PIPE)
        tr2 = Popen(['tr', r"'\040'", r"';'"], stdin=tr1), stdout=PIPE)
        cut = Popen(['cut', r"-d", r"\;", '-f', '3'], stdin=tr2, stdout=PIPE)
        return cut.stdout.read()
    
  • 後続の各コマンドで、プロセスではなく、Popenオブジェクトを渡しましたstdout。サブプロセスドキュメントの「シェルパイプラインの置き換え」セクションから、実行します

    p1 = Popen(["dmesg"], stdout=PIPE)
    p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
    

    stdin=p1..あなたは。と同等のことをしていましたが

    tr1 =上記の書き直されたコードでは)行はになります。

    tr1 = Popen(['tr', '-s', r"'\040'"], stdin=blame.stdout, stdout=PIPE)
    
  • サブプロセスはどのシェルでもコマンドを実行しないため(指定しない限り)、サブプロセスでコマンド/引数をエスケープする必要はありませんshell=True。サブプロセスドキュメントの「セキュリティ」セクションを参照してください。

    それ以外の..

    proc.append(Popen(['svn', 'blame', shellquote(filename)], stdout=PIPE))
    

    ..あなたは安全に行うことができます..

    Popen(['svn', 'blame', filename], stdout=PIPE)
    
  • S.Lottが示唆したように、Pythonでテキスト操作を簡単に行うためにサブプロセスを使用しないでください(tr / cutコマンド)。一つには、tr / cutなどはあまり移植性がなく(バージョンが異なれば引数も異なります)、読みにくいです(trとcutが何をしているのかわかりません)

    コマンドを書き直すとしたら、おそらく次のようなことをします。

    def get_blame(filename): 
        blame = Popen(['svn', 'blame', filename], stdout=PIPE)
        output = blame.communicate()[0] # preferred to blame.stdout.read()
        # process commands output:
        ret = []
        for line in output.split("\n"):
            split_line = line.strip().split(" ")
            if len(split_line) > 2:
                rev = split_line[0]
                author = split_line[1]
                line = " ".join(split_line[2:])
    
                ret.append({'rev':rev, 'author':author, 'line':line})
    
        return ret
    
于 2009-04-22T17:13:09.420 に答える
1

stdin=proc[-1]プロセスの標準が必要なので、次のように置き換えますstdin=proc[-1].stdout

また、あなたはあなたの親を動かす必要があります、それはstdout議論の後に来るべきです。

 proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1]), stdout=PIPE)

する必要があります:

 proc.append(Popen(['tr', '-s', r"'\040'"], stdin=proc[-1].stdout, stdout=PIPE))

append同じ方法で他の呼び出しを修正します。

于 2009-04-22T16:11:54.997 に答える
-1

構文エラーのように見えます。最初に追加することを除いて、残りは誤りです(括弧を確認してください)。

于 2009-04-22T16:11:38.353 に答える
-2

S.Lottが言ったように、Pythonでテキストを処理する方が優れています。

ただし、cmdlineユーティリティを使用する場合は、次を使用して読みやすくすることができますshell=True

cmdline = r"svn blame %s | tr -s '\040' | tr '\040' ';' | cut -d \; -f 3" % shellquote(filename)
return Popen(cmdline, shell=True, stdout=PIPE).communicate()[0]
于 2009-04-22T18:01:31.177 に答える