/ / Pythonサブプロセス「オブジェクトに属性 'fileno'がありません」エラー-Python、パイプ、サブプロセス

Pythonサブプロセス "オブジェクトに属性 'fileno'がありません" - python、pipe、subprocessエラー

このコードは、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""40""], stdin=proc[-1]), stdout=PIPE)
proc.append(Popen(["tr", r""40"", 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""40""], 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 docs describeで動作するはずです この使用法.

回答:

回答№1の場合は10

三つのこと

まず、() "が間違っています。

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

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

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

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

第三に、すべてをやらないでください tr そして cut シェル内のジャンク、より遅いものはほとんどありません。書きます tr そして cut Pythonでの処理-より高速で簡単です。


回答№2の場合は3

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

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

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

    そのため、ストレートリライト(まだエラーが発生します)になります。

    def get_blame(filename):
    blame = Popen(["svn", "blame", shellquote(filename)], stdout=PIPE)
    tr1 = Popen(["tr", "-s", r""40""], stdin=blame, stdout=PIPE)
    tr2 = Popen(["tr", r""40"", 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""40""], 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コマンド)。読むために

    コマンドを書き換えるとしたら、おそらく次のようなことをするでしょう。

    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
    

回答№3の場合は1

プロセスの標準出力が必要なため、 stdin=proc[-1] 〜と stdin=proc[-1].stdout

また、括弧を移動する必要があります。 stdout 引数。

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

次のようにする:

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

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


回答№4の場合は-1

構文エラーのように見えます。最初の追加を除いて、残りは間違っています(レビューブラケット)。


回答№5の場合-2

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

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

cmdline = r"svn blame %s | tr -s "40" | tr "40" ";" | cut -d ; -f 3" % shellquote(filename)
return Popen(cmdline, shell=True, stdout=PIPE).communicate()[0]