子进程未能捕获标准输出

1 投票
4 回答
1542 浏览
提问于 2025-04-15 22:50

我正在尝试用fasta文件作为输入来生成树形结构,并使用MuscleCommandline进行对齐。

import sys,os, subprocess
from Bio import AlignIO
from Bio.Align.Applications import MuscleCommandline
cline = MuscleCommandline(input="c:\Python26\opuntia.fasta")
child= subprocess.Popen(str(cline),
                         stdout = subprocess.PIPE,
                         stderr=subprocess.PIPE,
                        shell=(sys.platform!="win32"))
align=AlignIO.read(child.stdout,"fasta")
outfile=open('c:\Python26\opuntia.phy','w')
AlignIO.write([align],outfile,'phylip')
outfile.close()

我总是遇到这些问题。

Traceback (most recent call last):
  File "<string>", line 244, in run_nodebug
  File "C:\Python26\muscleIO.py", line 11, in <module>
    align=AlignIO.read(child.stdout,"fasta")
  File "C:\Python26\Lib\site-packages\Bio\AlignIO\__init__.py", line 423, in read
    raise ValueError("No records found in handle")
ValueError: No records found in handle

4 个回答

2

来自于 subprocess库 的文档:

警告

使用 communicate() 方法,而不是 .stdin.write、.stdout.read 或 .stderr.read,这样可以避免因为 其他操作系统的管道缓冲区 被填满而导致的死锁问题, 进而阻塞子进程。

所以你可以试试这样的做法:

mydata = child.communicate()[0]
4

这里有几个问题需要注意:

  1. 在调用外部程序后,你需要加上 child.wait(),这样你的代码才能等到外部程序运行完毕再继续。

  2. 虽然帮助文档上说 Muscle 会写入 stdout,但实际上它并没有这样做,至少在我这里的 v3.6 版本是这样的。我相信最新的版本是 v3.8,所以这个问题可能已经修复了。

Biopython 提示你传给它的 stdout 是空的,这就是你看到的错误。你可以直接在命令行运行这个:

muscle -in opuntia.fasta

看看是否能看到 FASTA 的输出。这里有一个修复了等待问题并使用中间输出文件的版本:


import sys,os, subprocess
from Bio import AlignIO
from Bio.Align.Applications import MuscleCommandline
out_file = "opuntia.aln"
cline = MuscleCommandline(input="opuntia.fasta", out=out_file)
child= subprocess.Popen(str(cline),
                         stdout = subprocess.PIPE,
                         stderr=subprocess.PIPE,
                        shell=(sys.platform!="win32"))
child.wait()
with open(out_file) as align_handle:
    align=AlignIO.read(align_handle,"fasta")
outfile=open('opuntia.phy','w')
AlignIO.write([align],outfile,'phylip')
outfile.close()
os.remove(out_file)

0

今天发布了Biopython 1.54版本,其中包含了Bio.Phylo模块的稳定版本。我已经更新了文档,里面有一个生成树的示例流程。为了简单起见,这个示例使用ClustalW来对序列进行比对并生成树,而不是使用Muscle和Phylip,但大部分代码还是差不多的。

http://biopython.org/wiki/Phylo#Example_pipeline

如果你已经用Phylip生成过树(使用.phy格式的比对作为输入),你仍然可以大致跟着Phylo的示例来操作。Phylip会生成一个Newick格式的文件,文件名可能是“outttree”或者“foo.tree”。

(欢迎把这个和Brad的回答合并;我现在还不能在那个讨论里评论。)

撰写回答