gpt4 book ai didi

python - 用 Python 的 Popen 替换 Bash 风格的进程

转载 作者:太空狗 更新时间:2023-10-30 01:55:06 24 4
gpt4 key购买 nike

在 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

您可以在第二个示例中看到 bash 如何自动创建文件描述符并允许您将程序的输出传递给另一个程序。

现在回到我的问题:如何在 Python 中使用子进程模块中的 Popen 来做同样的事情?

我一直在使用一个普通的 kmers 文件并只是读入它,但我的程序现在根据用户参数在运行时生成一个特定的 kmers 列表。我想避免手动写入临时文件,因为处理文件权限可能会给我的原始用户带来问题。

这是我的代码,用于运行我的程序并使用实际文件“kmer_file”捕获标准输出

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

我创建了一个名为 generate_kmers 的函数,它返回一个字符串,该字符串可以轻松写入文件(包括换行符)或 StringIO。我还有一个独立的 python 脚本来做同样的事情

所以现在我想将它作为我的第三个参数传递:

这行不通:

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 选项并使用 <() 的实际 bashism,但我还没有弄清楚。

谢谢!

最佳答案

如果 pram_axdnull"-" 约定理解为:“从标准输入读取”,那么您可以:

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

为了避免等待生成所有 kmers,即同时写入/读取 kmers,您可以在 Unix 上使用 os.mkfifo()(@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 - 用 Python 的 Popen 替换 Bash 风格的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15343447/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com