与Python的POPEN击风格进程替换 [英] Bash style process substitution with Python's Popen

查看:184
本文介绍了与Python的POPEN击风格进程替换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在bash,那么你可以将进程的输出重定向轻松到一个临时文件的描述符,它是所有的bash这样的自动处理的:

In Bash you can easily redirect the output of a process to a temporary file descriptor and it is all automagically handled by bash like this:

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

或者是这样的:

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

怎么看它是不是标准输入重定向:

see how it is not stdin redirection:

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

您可以在第二个例子是如何的bash会自动创建一个文件描述符,并允许你的程序的输出传递到另一个程序看到的。

You can see in the second example how bash automatically creates a file descriptor and allows you to pass the output of a program to another program.

现在到我的问题:我如何可以做同样的事情与Python,子模块中使用POPEN

Now onto my question: How can I do the same thing with Python, using Popen in the subprocess module?

我一直在使用kmers的正常文件,只是读它,但我的程序现在可以生成基于用户参数在运行时kmers的具体名单。我想避免编写一个临时文件手动因为处理文件权限可能会导致问题,为我的原始用户。

I have been using a normal file of kmers and just reading it in, but my program now generates a specific list of kmers at runtime based on user parameters. I'd like to avoid writing to a temporary file manually because dealing with file permissions could cause problems for my primitive users.

下面是我的code运行我的程序和实际文件kmer_file

Here is my code to run my program and capture the stdout with an actual file "kmer_file"

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

我创建了一个函数调用generate_kmers它返回一个可以写入到文件中轻松(包括新行)或一个StringIO的字符串。我也有一个python脚本是独立做同样的事情。

I created a function called generate_kmers which returns a string that can be written out to a file easily (includes newlines) or to a StringIO. I also have a python script that is standalone to do the same thing

所以,现在我想在把它作为我的第3个参数:

So now I want to pass it in as my 3rd parameter:

这不工作:

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选项思维和使用&LT的实际bashism;(),但我还没有想通了这一点。

Does anyone know of a good way to resolve this? I was thinking using the shell=True option and using the actual bashism of <() but I haven't figured that out.

感谢您!

推荐答案

如果 pram_axdnull 理解 - 会议意味着:从标准输入读取,那么你可以:

If pram_axdnull understands "-" convention to mean: "read from stdin" then you could:

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

如果由外部处理生成的输入:

If the input is generated by external process:

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)

要使用外部程序生成的临时文件:

To generate temporary file using external process:

from subprocess import check_call

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

要避免等待中,即生成的所有kmers,写入/读取同时kmers,你可以使用 os.mkfifo()在Unix(由@cdarke建议)

To avoid waiting for all kmers to be generated i.e., to write/read kmers simultaneously, you could use os.mkfifo() on Unix (suggested by @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()

这篇关于与Python的POPEN击风格进程替换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆