69

subprocessPythonモジュールを使用して次のシェル コマンドを実行するにはどうすればよいですか?

echo "input data" | awk -f script.awk | sort > outfile.txt

入力データは文字列から取得されるため、実際には必要ありませんecho。私はここまで来ましたが、パイプを通過させる方法を誰か説明できsortますか?

p_awk = subprocess.Popen(["awk","-f","script.awk"],
                          stdin=subprocess.PIPE,
                          stdout=file("outfile.txt", "w"))
p_awk.communicate( "input data" )

更新:以下の受け入れられた回答は実際には質問に答えていませんが、S.Lottは正しいと信じており、そもそもその問題を解決する必要はありません!

4

9 に答える 9

51

あなたは次のことで少し幸せになるでしょう.

import subprocess

awk_sort = subprocess.Popen( "awk -f script.awk | sort > outfile.txt",
    stdin=subprocess.PIPE, shell=True )
awk_sort.communicate( b"input data\n" )

作業の一部をシェルに委譲します。2 つのプロセスをパイプラインで接続します。

'script.awk' を Python に書き直して、awk とパイプラインをなくせば、もっと幸せになれるでしょう。

編集します。awk が役に立たないことを示唆する理由のいくつか。

[コメントで返信するには理由が多すぎます。]

  1. awk は、重要な価値のないステップを追加しています。Python が処理しない awk の処理に固有のものは何もありません。

  2. awk から sort へのパイプライン処理により、大量のデータ セットの場合、経過処理時間が改善される場合があります。短いデータ セットの場合、大きなメリットはありません。同時実行性の迅速な測定awk >file ; sort fileと明らかにすることが役立ちます。awk | sort並べ替えでは、並べ替えは 1 回限りのフィルターではないため、ほとんど役に立ちません。

  3. 「Python からソート」処理 (「Python から awk からソート」ではなく) の単純さは、ここで尋ねられる正確な種類の質問を妨げます。

  4. Python は awk よりも語彙が多いですが、明示的ですが、awk には特定の暗黙のルールがあり、初心者にはわかりにくく、専門家以外には混乱を招きます。

  5. Awk (シェル スクリプト自体と同様) は、Yet Another プログラミング言語を追加します。これらすべてを 1 つの言語 (Python) で実行できる場合、シェルと awk プログラミングを排除すると、2 つのプログラミング言語が不要になり、誰かがタスクの価値を生み出す部分に集中できるようになります。

結論: awk は大きな価値を追加することはできません。この場合、awk は純コストです。この質問をする必要があるほどの複雑さが追加されました。awk を削除すると、純利益が得られます。

サイドバーパイプライン ( a | b) の構築が非常に難しい理由。

シェルが直面するとa | b、次のことを行う必要があります。

  1. 元のシェルの子プロセスを fork します。これは最終的にbになります。

  2. os パイプを構築します。(Python subprocess.PIPE ではありません) しかし、os.pipe()共通バッファーを介して接続された 2 つの新しいファイル記述子を返す呼び出し。この時点で、プロセスには、その親からの stdin、stdout、stderr に加えて、「a の stdout」および「b の stdin」となるファイルがあります。

  3. 子供をフォークします。子は、その stdout を新しい a の stdout に置き換えます。プロセスを実行しaます。

  4. b の子を閉じると、その stdin が新しい b の stdin に置き換えられます。プロセスを実行しbます。

  5. b 子は a が完了するのを待ちます。

  6. 親は b が完了するのを待っています。

上記は spawn に再帰的に使用できると思いますが、a | b | c長いパイプラインを暗黙的に括弧で囲み、あたかも であるかのように扱う必要がありますa | (b | c)

Python にはと がありos.pipe()、とを置き換えることができるため、純粋な Python で上記を行う方法があります。実際、 と を使用していくつかのショートカットを作成できる場合があります。os.exec()os.fork()sys.stdinsys.stdoutos.pipe()subprocess.Popen

ただし、その操作をシェルに委譲する方が簡単です。

于 2008-11-17T13:32:13.787 に答える
31
import subprocess

some_string = b'input_data'

sort_out = open('outfile.txt', 'wb', 0)
sort_in = subprocess.Popen('sort', stdin=subprocess.PIPE, stdout=sort_out).stdin
subprocess.Popen(['awk', '-f', 'script.awk'], stdout=sort_in, 
                 stdin=subprocess.PIPE).communicate(some_string)
于 2012-02-06T17:20:01.037 に答える
20

シェル パイプラインをエミュレートするには:

from subprocess import check_call

check_call('echo "input data" | a | b > outfile.txt', shell=True)

シェルを呼び出さずに (「17.1.4.2. シェル パイプラインの置き換え」を参照):

#!/usr/bin/env python
from subprocess import Popen, PIPE

a = Popen(["a"], stdin=PIPE, stdout=PIPE)
with a.stdin:
    with a.stdout, open("outfile.txt", "wb") as outfile:
        b = Popen(["b"], stdin=a.stdout, stdout=outfile)
    a.stdin.write(b"input data")
statuses = [a.wait(), b.wait()] # both a.stdin/stdout are closed already

plumbumいくつかの構文シュガーを提供します。

#!/usr/bin/env python
from plumbum.cmd import a, b # magic

(a << "input data" | b > "outfile.txt")()

類似物:

#!/bin/sh
echo "input data" | awk -f script.awk | sort > outfile.txt

は:

#!/usr/bin/env python
from plumbum.cmd import awk, sort

(awk["-f", "script.awk"] << "input data" | sort > "outfile.txt")()
于 2013-05-23T09:01:24.997 に答える
2

http://www.python.org/doc/2.5.2/lib/node535.htmlはこれをかなりうまくカバーしています。これでわからなかった部分はありますか?

あなたのプログラムはかなり似ていますが、2番目Popenはファイルへのstdout =を持ち、その.communicate().

于 2008-11-17T12:26:50.890 に答える
1

編集: Windows で使用できますが、重要なことに、実際には Windows で 動作pipesしないようです。以下のコメントを参照してください。

Python 標準ライブラリには、pipesこれを処理するためのモジュールが含まれるようになりました。

https://docs.python.org/2/library/pipes.htmlhttps://docs.python.org/3.4/library/pipes.html

このモジュールがどのくらいの期間使用されているかはわかりませんが、このアプローチは をいじるよりもはるかに簡単なようsubprocessです。

于 2014-12-04T18:51:58.210 に答える