我正在编写一个需要调用外部程序hmm3align的Python程序,该程序从命令行运行如下:
hmm3align hmm_file fasta_file -o output_file
通常,程序需要两个输入文件并将结果写入第三个文件。我的程序实际上有多个调用外部程序的情况,但这是外部程序有两个文件输入的唯一情况。我的目的是避免编写和读取文件以允许这些外部程序相互通信;我希望在会话期间将所有数据存储为Python变量,并在需要时将这些变量提供给外部程序。
在需要调用hmm3align的Python程序中,我已经有两个Python变量hmm_model和fasta_model,它们分别包含通常包含在hmm_file和fasta_file中的信息。我想做的是通过stmm传递hmm_model和fasta_model来调用hmm3align(因为我认为这是将它们作为输入提供的唯一方法),然后将stdout中的结果捕获到名为align_results的第三个Python变量中。为此,我创建了一个单独的函数,它使用子进程模块,如下所示:
def hmmalign(hmm_model,fasta):
args = ["/clusterfs/oha/software/bin/hmm3align",
"-", "-",
"-o", "/dev/stdout"]
process = subprocess.Popen(args, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return process.communicate(hmm_model,fasta)[0]
所以你可以看到,我试图通过stdin发送两个变量。 args列表中的两个“ - ”用于捕获这两个变量;我看过其他例子中使用的“ - ”,但其目的不明确,我可能误解了事情。
果然,我在Traceback结束时收到以下错误:
TypeError: communicate() takes at most 2 arguments (3 given)
所以我不能通过stdin将两个单独的变量传递给程序。我应该提一下,当该程序只需要一个输入文件时,我已经能够在类似的外部程序上运行子进程。
如何使这项工作?是否可以使用具有多个输入的子进程?我查看了文档并没有看到这个问题的答案。提前谢谢。
答案 0 :(得分:1)
标准输入是单个数据流;在Unix上,它是连接到单向管道的输出端的文件描述符。按照惯例,从命令行上指定的单个文件读取的程序将-
理解为从stdin而不是从文件读取的指令。但是,对于从两个文件读取的程序,无法从stdin读取两次,因为它是单个数据流。
还有其他文件描述符可用于通信(stdin是fd 0,stdout是fd 1,stderr是fd 2)但是没有传统的方法来指定它们而不是文件。
最有可能在这里工作的解决方案是 named pipes (FIFO);在Python中,使用os.mkfifo
创建命名管道,使用os.unlink
删除它。然后,您可以在写入程序时将其名称传递给程序(它将显示为可以读取的文件)(使用open
)。