7

Bashでは、プロセスの出力を一時ファイル記述子に簡単にリダイレクトでき、すべて次のようにbashによって自動的に処理されます。

$ mydaemon --config-file <(echo "autostart: True \n daemonize: True")

またはこのように:

$ wc -l <(ls)
15 /dev/fd/63

stdinリダイレクションではないことを確認してください。

$ vim <(echo "Hello World") 
vim opens a text file containing "Hello world"
$ echo  "Hello World" | vim
Vim: Warning: Input is not from a terminal

2番目の例では、bashがファイル記述子を自動的に作成し、プログラムの出力を別のプログラムに渡すことができる方法を確認できます。

今私の質問に移ります:サブプロセスモジュールでPopenを使用して、Pythonで同じことをどのように行うことができますか?

私はkmersの通常のファイルを使用してそれを読み込んでいますが、私のプログラムはユーザーパラメータに基づいて実行時にkmersの特定のリストを生成するようになりました。ファイルのアクセス許可を処理すると、プリミティブユーザーに問題が発生する可能性があるため、一時ファイルに手動で書き込むことは避けたいと思います。

これが私のプログラムを実行し、実際のファイル「kmer_file」でstdoutをキャプチャするための私のコードです

input_file = Popen(["pram_axdnull", str(kmer), input_file, kmer_file], stdout=PIPE)

ファイル(改行を含む)またはStringIOに簡単に書き出すことができる文字列を返すgenerate_kmersという関数を作成しました。同じことをするためにスタンドアロンのPythonスクリプトもあります

だから今私はそれを私の3番目のパラメーターとして渡したい:

これは機能しません:

kmer_file = stringIO(generate_kmers(3))
input_file = Popen(["pram_axdnull", str(kmer), input_file, kmer_file], stdout=PIPE)

これもしません:

kmer_file = Popen(["generate_kmers", str(kmer)], stdout=PIPE)
input_file = Popen(["pram_axdnull", str(kmer), input_file, kmer_file.stdout], stdout=PIPE)

だから私はアイデアがありません。

誰かがこれを解決するための良い方法を知っていますか?私はshell=Trueオプションを使用し、<()の実際のバシズムを使用することを考えていましたが、それを理解していません。

ありがとうございました!

4

1 に答える 1

14

pram_axdnull規則が「stdinから読み取る」という意味であると理解している場合"-"は、次のことができます。

p = Popen(["pram_axdnull", str(kmer), input_filename, "-"],
          stdin=PIPE, stdout=PIPE)
output = p.communicate(generate_kmers(3))[0]

入力が外部プロセスによって生成された場合:

kmer_proc = Popen(["generate_kmers", str(kmer)], stdout=PIPE)
p = Popen(["pram_axdnull", str(kmer), input_filename, "-"],
          stdin=kmer_proc.stdout, stdout=PIPE)
kmer_proc.stdout.close()
output = p.communicate()[0]

規則を理解pram_axdnull していない場合:"-"

import os
import tempfile
from subprocess import check_output

with tempfile.NamedTemporaryFile() as file:
    file.write(generate_kmers(3))
    file.delete = False

try:
    p = Popen(["pram_axdnull", str(kmer), input_filename, file.name],
              stdout=PIPE)
    output = p.communicate()[0]
    # or
    # output = check_output(["pram_axdnull", str(kmer), input_filename, 
                             file.name])
finally:
    os.remove(file.name)

外部プロセスを使用して一時ファイルを生成するには:

from subprocess import check_call

with tempfile.NamedTemporaryFile() as file:
    check_call(["generate_kmers", str(kmer)], stdout=file)
    file.delete = False

すべてのkmerが生成されるのを待つのを避けるために、つまりkmerの書き込み/読み取りを同時に行うにはos.mkfifo()、Unixで使用できます(@cdarkeが推奨)。

import os
import shutil
import tempfile
from contextlib import contextmanager
from subprocess import Popen, PIPE

@contextmanager
def named_pipe():
    dirname = tempfile.mkdtemp()
    try:
        path = os.path.join(dirname, 'named_pipe')
        os.mkfifo(path)
        yield path
    finally:
        shutil.rmtree(dirname)

with named_pipe() as path:
    p = Popen(["pram_axdnull", str(kmer), input_filename, path],
              stdout=PIPE) # read from path
    with open(path, 'wb') as wpipe:
        kmer_proc = Popen(["generate_kmers", str(kmer)],
                          stdout=wpipe) # write to path
    output = p.communicate()[0]
    kmer_proc.wait()
于 2013-03-11T16:30:56.230 に答える