【发布时间】:2012-10-07 18:25:22
【问题描述】:
背景:
Linux 上的 Python 2.6.6。 DNA 序列分析流程的第一部分。
我想从已安装的远程存储 (LAN) 中读取可能压缩过的文件,如果它是压缩过的; gunzip 将其压缩到一个流中(即使用gunzip FILENAME -c),如果流(文件)的第一个字符是“@”,则将整个流路由到一个过滤程序中,该程序接受标准输入的输入,否则只需将其直接通过管道传输到本地磁盘上的文件。我想尽量减少从远程存储读取/查找文件的次数(只通过文件一次应该不是不可能的吗?)。
示例输入文件的内容,前四行对应一条 FASTQ 格式的记录:
@I328_1_FC30MD2AAXX:8:1:1719:1113/1
GTTATTATTATAATTTTTTACCGCATTTATCATTTCTTCTTTATTTTCATATTGATAATAAATATATGCAATTCG
+I328_1_FC30MD2AAXX:8:1:1719:1113/1
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhahhhhhhfShhhYhhQhh]hhhhffhU\UhYWc
不应通过管道传输到过滤程序的文件包含如下所示的记录(前两行对应于 FASTA 格式的一条记录):
>I328_1_FC30MD2AAXX:8:1:1719:1113/1
GTTATTATTATAATTTTTTACCGCATTTATCATTTCTTCTTTATTTTCATATTGATAATAAATATATGCAATTCG
有些人编造了半伪代码来可视化我想要做什么(我知道这不可能像我写的那样)。我希望它有一些意义:
if gzipped:
gunzip = Popen(["gunzip", "-c", "remotestorage/file.gz"], stdout=PIPE)
if gunzip.stdout.peek(1) == "@": # This isn't possible
fastq = True
else:
fastq = False
if fastq:
filter = Popen(["filter", "localstorage/outputfile.fastq"], stdin=gunzip.stdout).communicate()
else:
# Send the gunzipped stream to another file
忽略这样一个事实,即代码不会像我在这里写的那样运行,而且我没有错误处理等,所有这些都已经在我的其他代码中了。我只是想要帮助窥视溪流或找到解决方法。如果你能gunzip.stdout.peek(1) 我会很棒,但我意识到这是不可能的。
到目前为止我所做的尝试:
我认为 subprocess.Popen 可能会帮助我实现这一点,并且我尝试了很多不同的想法,其中包括尝试使用某种 io.BufferedRandom() 对象来写入流,但我不知道是怎么做到的会工作。我知道流是不可搜索的,但也许一种解决方法可能是读取 gunzip-stream 的第一个字符,然后创建一个新流,您首先根据文件内容输入“@”或“>”,然后填充其余部分的 gunzip.stdout-stream 到新的流。然后将这个新流输入过滤器的 Popen 标准输入。
请注意,文件大小可能比可用内存大几倍。我不想从远程存储中对源文件执行一次以上的读取,也不想进行不必要的文件访问。
欢迎任何想法!如果我说得不够清楚,请向我提问。
【问题讨论】:
-
使用gzip 模块而不是外部
gzip应该会给您更多的灵活性。 -
@PedroRomano 是的,它可能会。我担心我进行的文件访问次数。这将是在超级计算机系统上实现的管道的数据采集步骤的一部分,并且可能会同时在多个节点上运行,过多的文件系统调用可能会使远程文件服务器陷入困境。