我正在尝试读取一个gtf文件,然后在加载到pandas之前对其进行编辑(使用subprocess,grep和awk)。
我有一个包含标题信息的文件名(由#
表示),所以我需要先将其删除并先将其删除。我可以在python中完成它,但我想在我的管道中引入grep
以提高处理效率。
我尝试过:
import subprocess
from io import StringIO
gtf_file = open('chr2_only.gtf', 'r').read()
gtf_update = subprocess.Popen(["grep '^#' " + StringIO(gtf_file)], shell=True)
和
gtf_update = subprocess.Popen(["grep '^#' " + gtf_file], shell=True)
这两个代码都会抛出错误,第一次尝试是:
Traceback (most recent call last):
File "/home/everestial007/PycharmProjects/stitcher/pHASE-Stitcher-Markov/markov_final_test/phase_to_vcf.py", line 39, in <module> gtf_update = subprocess.Popen(["grep '^#' " + StringIO(gtf_file)], shell=True)
TypeError: Can't convert '_io.StringIO' object to str implicitly
但是,如果我直接指定文件名,它可以工作:
gtf_update = subprocess.Popen(["grep '^#' chr2_only.gtf"], shell=True)
,输出为:
<subprocess.Popen object at 0x7fc12e5ea588>
#!genome-build v.1.0
#!genome-version JGI8X
#!genome-date 2008-12
#!genome-build-accession GCA_000004255.1
#!genebuild-last-updated 2008-12
有人可以提供这样的问题的不同示例,并解释为什么我会收到错误以及为什么/如何直接在控制台/内存上加载的文件上运行子进程?
我也尝试将subprocess
与call, check_call, check_output, etc.
一起使用,但我收到了几条不同的错误消息,例如:
OSError: [Errno 7] Argument list too long
和
Subprocess in Python: File Name too long
答案 0 :(得分:2)
这是一个可能的解决方案,允许您将字符串发送到grep。基本上,您在Popen
构造函数中声明要通过stdin和stdout与被调用程序进行通信。然后通过通信发送输入,并从通信接收输出作为返回值。
#!/usr/bin/python
import subprocess
gtf_file = open('chr2_only.gtf', 'r').read()
gtf_update = subprocess.Popen(["grep '^#' "], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
# stdout, stderr (but latter is empty)
gtf_filtered, _ = gtf_update.communicate(gtf_file)
print gtf_filtered
请注意,不使用shell=True
是明智的。因此,Popen行应写为
gtf_update = subprocess.Popen(["grep", '^#'], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
理由是你不需要shell来解析单个可执行文件的参数。所以你避免了不必要的开销从安全的角度来看,它也更好,至少如果某些参数可能不安全,因为它来自用户(想想包含|
的文件名)。 (这显然不是这种情况。)
请注意,从性能的角度来看,我希望直接使用grep
读取文件比首先使用python读取文件,然后将其发送到grep。